2016-01-15 50 views
0

我是iOS應用程序開發新手,我製作了一個包含文本字段,插入按鈕和表格的應用程序。如何在iOS中保存.plist文件(例如iPhone)?

因此,當文本字段中輸入內容時,它會顯示在表格中。

當應用程序進入背景或終止,其保存該列表如下:

- (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:對不起,如果我是冗長的。謝謝。

+0

爲什麼不使用NSUserDefaults來保存應用程序的數據?如果你想使用它,我也可以分享一些代碼示例。 – Aamir

+0

沒有保留plist文件的概念。你可以發佈你寫的代碼來顯示.plist文件數據在tableview中(對於你的語句:「在殺死應用程序並再次打開應用程序後,我沒有返回列表(僅在我的iPhone上,在模擬器上它工作精細)」)。 –

+0

我看不到任何代碼來加載'.plist'文件。同樣,這兩種方法也會執行相同的操作,所以應將功能移至常用方法。 – trojanfoe

回答

0

只需加載該文件早在applicationDidBecomeActiveapplicationDidFinishLaunching,假設該文件已成功創建,它不以某種方式讓你關閉應用程序,並重新啓動它的時候,這不應該發生之間刪除,除非你清洗構建容器文件明確,但我懷疑它。

3

方法-writeToFile:atomically:返回BOOL,指示寫入操作是否成功。

在你的情況下,它會在模擬器上成功,因爲你正在寫入到你的Mac磁盤,因爲你的進程對你的應用程序包有寫入權限。設備上並非如此:由於應用程序是代碼簽名的,因此該軟件包是隻讀的,並且無法向其中寫入文件,因此該方法將返回NO

你應該經常檢查這個值,並做出適當的迴應。還有一種方法需要一個NSError指針,所以你可以看到寫操作失敗的原因。

請記住,-writeToFile:atomically:是一個同步操作,它會阻塞它被調用的線程。一般情況下,您希望避免阻塞主線程,因此最好在另一個線程上運行該方法(查找dispatch_async()和GCD文檔)。在你的情況下,你在applicationWillTerminate:中調用它,這是你應用程序的最後一次呼吸,你不想調度到另一個線程,因爲它會在applicationWillTerminate:返回後與後應用程序一起死亡,並且很可能在該次要線程之前一個完成的機會。但是,請注意,applicationWillTerminate:可能不是保存狀態的最佳位置,因爲時間短暫,但也是因爲只有當您的應用程序將真正終止時纔會調用此方法(當您按Home鍵時不會調用此方法例)。查看其他應用程序生命週期方法的文檔,找出最適合您的日期的位置,您可能會發現,您甚至不需要使用這些方法,但可以在應用程序啓動時立即完成保存工作運行。無論你的目的是什麼。

爲了得到一個目錄,你可以寫,你可以使用例如下面的代碼:

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

另外,他不檢查'-writeToFile:atomically:'的返回值並記錄「SAVED」。 –

+0

糟糕,你已經在你的答案中提到過它;我評論得太快了。 –

+0

+1:關於檢查保存是否成功以及無法寫入捆綁包的好處。原因不是代碼簽名,但是(它是沙盒)。此外,在這種情況下,在後臺保存文件的建議過於籠統和徹底錯誤:在調用applicationWillTerminate時,應用即將被拉取。應用程序將繼續運行,直到方法完成,因此保存同步是確保在進程被終止前保存文件的唯一方法。 –

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; 
} 

所以,現在應用程序按預期工作。感謝你們。

+0

這看起來像一個工作實現,非常棒!請注意,當您仍然在主線程上同步加載數據時,所以當有大文件需要加載時,應用程序在加載時不會響應。您可以像保存一樣在後臺加載數據,然後通過從塊內再次調度到主隊列(dispatch_get_mainqueue())將tasks-array分配給viewController。請記住,didFinishLauchingWithOptions:只能從「冷」啓動中調用,而不是在它回到前臺時調用。 – Joride

相關問題