3

好的,我目前有一个主从应用程序,它有一个带有导航控制器的表视图、一个详细视图和一个模式视图。导航视图显示饮品名称,详细视图显示所选饮品的详细信息,模态视图允许我创建新饮品或编辑现有饮品。一切都是从我已经移动到文档目录的 plist 中填充的,并且一切都可以正常读取。我知道这是可行的,因为我已经用一个空的 plist 进行了测试,看看我的视图是否变为空白,并且它们成功了。我所有的观点都很完美。我可以添加编辑和删除饮料,并且我的表格视图会使用新的或删除的或更改的饮料进行更新。但是它没有成功写入 plist 文件(我正在从我的 masterViewController 中名为“drinks”的数组更新我的 plist)。

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [searchPaths objectAtIndex:0];
    NSString *writeableDBPath = [documentsDirectory stringByAppendingPathComponent:@"DrinkDirections.plist"];

    [self.drinks writeToFile:writeableDBPath atomically:YES];
}

我通过放置 2 个 NSLogs() 对此进行了测试:一个在我放置在我的 masterViewController 中的 applicationWillTerminate 方法中,一个在我的 AppDelegate.m 中的 applicationWillTerminate 方法中。该日志仅显示在 AppDelegate.m 中的控制台中。所以最后我不知道如何从我的 AppDelegate.m 文件中访问我的 MasterViewController 中的饮料数组,所以我可以使用我的 appDelegate.m 中的 applicationWillTerminate 方法保存到 plist。我将在下面发布我的 appDelegate.m 代码,该代码会引发错误,因为饮料属性位于 MasterViewController 中。

AppDelegate.m(方法)

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [searchPaths objectAtIndex:0];
    NSString *writeableDBPath = [documentsDirectory stringByAppendingPathComponent:@"DrinkDirections.plist"];

    [self.drinks writeToFile:writeableDBPath atomically:YES]; //THIS LINE THROWS AN ERROR BECAUSE PROPERTY DRINKS IS ONLY ON MY MASTERVIEWCONTROLLER NOT MY AppDelegate

}
4

3 回答 3

4

首先,正如其他人在这里提到的那样,applicationDidEnterBackground:这可能是一个更好的地方。其次,您的视图控制器不会独自完成此调用:它是一个UIApplicationDelegate协议调用,而您的视图控制器不是其中之一。

你想要做的是让你的视图控制器收到UIApplicationDidEnterBackgroundNotification通知。 UIApplicationDelegate 参考说:

应用程序还会在调用此方法的同时发布 UIApplicationDidEnterBackgroundNotification 通知,让感兴趣的对象有机会响应转换。

所以在你的视图控制器中你想做这样的事情(警告:把这段代码直接输入网页,没有尝试编译它):

- (void) viewDidLoad
{
    [super viewDidLoad];

    // Register for notification.
    [[NSNotificationCenter defaultCenter] addObserver:self 
                          selector:@selector(applicationDidEnterBackground:) 
                              name:UIApplicationDidEnterBackgroundNotification
                            object:nil];
}

- (void) viewDidUnload
{
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
}

- (void) applicationDidEnterBackground:(NSNotification*)notification 
{
    // Do your plist saving here.
}
于 2012-06-27T03:30:52.060 回答
0

“对于支持后台执行的应用程序,当用户退出应用程序时,一般不会调用此方法,因为在这种情况下应用程序只是移动到后台”

http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html

简而言之:您的应用程序永远不会“终止”,而是置于后台并在必要时在后台终止。

由于应用程序默认“支持”背景,因此您应该考虑查看:

- (void)applicationDidEnterBackground:(UIApplication *)application
于 2012-06-26T23:55:59.757 回答
0

您也可以尝试在applicationDidEnterBackground调用时保存 .plist。根据苹果的文档here

在 iOS 4.0 及更高版本中,当用户退出支持后台执行的应用程序时,将调用此方法而不是 applicationWillTerminate: 方法。您应该使用此方法来释放共享资源、保存用户数据、使计时器无效并存储足够的应用程序状态信息以将您的应用程序恢复到其当前状态,以防以后终止。您还应该禁用对应用程序用户界面的更新,并避免使用某些类型的共享系统资源(例如用户的联系人数据库)。您还必须避免在后台使用 OpenGL ES。

我强调了相关部分。希望这可以帮助!

于 2012-06-27T00:00:12.497 回答