当应用程序终止时,尝试保存到plist

时间:2012-06-26 23:50:07

标签: objective-c ios xcode ios5

好的,我目前有一个Master-Detail应用程序,它有一个带有导航控制器的桌面视图,一个详细视图和一个模态视图。导航视图显示饮品名称,详细视图显示所选饮料详细信息,模态视图允许我创建新饮料或编辑现有饮品。所有东西都是从一个plist填充的,我已经移动到文档目录,所有内容都正好从它读取。我知道这是有效的,因为我已经测试了一个空的plist,看看我的视图是否变为空白,并且它们确实成功了。我的所有观点都很完美。我可以使用新的或删除或更改的饮料添加编辑和删除饮料以及我的表格视图更新。但是它没有成功写入plist文件(我正在从我的masterViewController中名为“drinks”的数组中更新我的plist)。我认为这是因为我试图在我的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];
}

我已经通过放置2个NSLogs()测试了这个:一个在applicationWillTerminate方法中我放在我的masterViewController中,一个放在appDelegate.m中的applicationWillTerminate方法中。该日志仅在控制台中显示AppDelegate.m中的日志。所以最后我无法弄清楚如何从我的AppDelegate.m文件中访问我的MasterViewController中的drink数组,这样我就可以使用appDelegate.m中的applicationWillTerminate方法保存到plist。我将在下面发布我的appDelegate.m代码,因为drink属性位于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

}

3 个答案:

答案 0 :(得分:4)

首先,正如其他人所说,applicationDidEnterBackground:可能是一个更好的地方。其次,你的视图控制器不会单独调用它:它是一个UIApplicationDelegate协议调用,你的视图控制器不是其中之一。

您要做的是让视图控制器收到UIApplicationDidEnterBackgroundNotification通知。 The UIApplicationDelegate reference说:

  

该应用程序还发布了一个   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.
}

答案 1 :(得分:0)

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

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

简而言之:你的申请永远不会被“终止”,而是放在后台并在必要时在后台被杀死。

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

- (void)applicationDidEnterBackground:(UIApplication *)application

答案 2 :(得分:0)

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

  

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

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