如何在iOS(例如iPhone)中保存.plist文件?

时间:2016-01-15 07:09:35

标签: ios objective-c iphone

我是iOS应用程序开发的新手,我创建了一个具有文本字段,插入按钮和表格的应用程序。

因此,当在文本字段中输入内容时,它会显示在表格中。

当应用程序进入后台或终止时,它会按如下方式保存该列表:

- (void)applicationDidEnterBackground:(UIApplication *)application 
{
    NSBundle *myApp = [NSBundle mainBundle];
    NSMutableString *fileDirectory = [[NSMutableString alloc] initWithString:[myApp bundlePath]];

    [fileDirectory appendString:@"/list.plist"];

    NSLog(@"%@", fileDirectory); //Just for refernece

    [self.viewController.tasks writeToFile:fileDirectory atomically:YES];

    NSLog(@"SAVED");
}

- (void)applicationWillTerminate:(UIApplication *)application {
    NSBundle *myApp = [NSBundle mainBundle];
    NSMutableString *fileDirectory = [[NSMutableString alloc] initWithString:[myApp bundlePath]];

    [fileDirectory appendString:@"/list.plist"];

    NSLog(@"%@", fileDirectory); //Just for refernece

    [self.viewController.tasks writeToFile:fileDirectory atomically:YES];

    NSLog(@"SAVED");
}

文件已保存。

杀死应用程序并再次打开应用程序后,我没有得到列表(仅在我的iPhone上,在模拟器上它工作正常)

是否可以在iPhone上保留列表?

P.S:对不起,如果我很啰嗦。谢谢。

3 个答案:

答案 0 :(得分:3)

方法-writeToFile:atomically:返回BOOL,表示写操作是否成功。

在您的情况下,它将在模拟器上成功,因为您正在写入您的Mac磁盘,这总是可以完成,因为您的进程具有对您的应用程序捆绑的写权限。在设备上不是这种情况:因为应用程序是代码签名的,所以捆绑包是只读的,并且您无法将文件写入其中,因此该方法将返回NO

您应该始终检查此值,并做出适当的回应。还有一个方法采用NSError指针,因此您可以看到写操作失败的原因。

请记住,-writeToFile:atomically:是一个同步操作,它将阻止调用它的线程。通常,您希望避免阻塞主线程,因此最好在另一个线程上运行该方法(查找dispatch_async()和GCD文档)。在你的情况下,你在applicationWillTerminate:中调用它,这是你的应用程序的最后一口气,你不想派遣到另一个线程,因为它会在applicationWillTerminate:返回后死于应用程序后死亡,并且很可能在该次要线程有机会完成之前。但请注意,applicationWillTerminate:可能不是保存状态的最佳位置,因为时间很短,但也因为只有当您的应用程序真正终止时才会调用此方法(当您按下时不会调用此方法)主页按钮例如)。查看有关其他应用程序生命周期方法的文档,以找出最佳保存日期的位置,您可能会发现您甚至不需要使用这些方法,但可以快速完成保存& #39;当应用程序运行时。无论什么适合你的目的。

要获取可以编写的目录,可以使用以下代码:

- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

答案 1 :(得分:0)

只需将文件重新加载到applicationDidBecomeActiveapplicationDidFinishLaunching,假设文件已成功创建,并且在您关闭应用程序并重新启动应用程序之间不会以某种方式删除文件,这应该是&n但是,除非您明确清理构建容器文件,否则我会对此表示怀疑。

答案 2 :(得分:0)

所以,我解决了这个问题。

现在代码在applicationDidEnterBackground中异步保存文件,如下所示:

- (void)applicationDidEnterBackground:(UIApplication *)application {
    typedef void (^block)();
    block theBlock;

    theBlock = ^(){
        BOOL fileWritten = [self.viewController.tasks writeToFile:self.viewController.savedList atomically:YES];

        if(fileWritten)
        {
            NSLog(@"Saved");
        }
    };

    /* Saving file Asynchronorusly */
    dispatch_queue_t myQueue = dispatch_queue_create("QUEUE-1",DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(myQueue, theBlock);

    }

并在applicationWillTerminate中同步如下:

- (void)applicationWillTerminate:(UIApplication *)application {

    /* Saving file Synchronously */

    BOOL fileWritten = [self.viewController.tasks writeToFile:self.viewController.savedList atomically:YES];

    if(fileWritten)
    {
        NSLog(@"Saved");
    }
}

那些指出我没有任何检索代码的人,对不起,我忘了提及它。它在applicationDidFinishLaunching中加载.plist,如下所示:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {


    [self.viewController myButton:nil];
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.viewController = [[ViewController alloc]initWithNibName:@"ViewController" bundle:nil];
    self.window.rootViewController = self.viewController;

    NSURL *fileDirectory = self.viewController.applicationDocumentsDirectory;

    NSMutableString *filePath = [[NSMutableString alloc] initWithString:[fileDirectory absoluteString]];
    [filePath appendString:@"list.plist"];
    filePath = (NSMutableString *)[filePath stringByReplacingOccurrencesOfString:@"file:///" withString:@""];

    self.viewController.savedList = filePath;

    if([[NSFileManager alloc] fileExistsAtPath:self.viewController.savedList])
    {
        self.viewController.tasks = [[NSMutableArray alloc] initWithContentsOfFile:self.viewController.savedList];
        NSLog(@"DATA READ: %@", self.viewController.tasks);
    }

    [self.window makeKeyAndVisible];

    return YES;
}

所以,现在应用程序按预期工作。谢谢你们。