2013-05-27 40 views
6

基於核心數據的iOS應用程序的一些客戶偶爾會丟失數據。這些報道非常奇怪,這就是我想要請你承擔這個問題的原因。客戶報告說,當他們在一段時間(幾分鐘,幾小時或次日)後重新打開應用程序時,他們的一些數據丟失,就好像底層數據庫恢復到之前的狀態一樣。核心數據沒有明顯原因地恢復到以前的狀態

我一直與核心數據工作了好幾年,從來沒有遇到過這樣的問題。該應用程序非常簡單,這意味着我只使用一個託管對象上下文,並且在應用程序轉到後臺之前提交更改。

我意識到這是一個遠射,但什麼可能是這種類型的問題的一些潛在原因或我可以做什麼檢查以收集更多信息?不幸的是,我不能自己重現這個問題,這會讓這一切變得更容易。

更新:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
    if (_persistentStoreCoordinator) return _persistentStoreCoordinator; 

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Prime.sqlite"]; 

    NSError *error = nil; 
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 

    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{ NSMigratePersistentStoresAutomaticallyOption : @YES, NSInferMappingModelAutomaticallyOption : @YES } error:&error]) { 
     // Error Handling 
    } 

    return _persistentStoreCoordinator; 
} 
+0

你設置任何['pragma'選項](http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/Articles/cdPersistentStores.html#//apple_ref/ doc/uid/TP40002875-SW12)在您的商店? –

+0

@DanShelly號我已經用你指的代碼片段更新了這個問題。 –

+1

當**完全**您是否保存更改? –

回答

2

檢查是否已將保存消息放在適當的appDelegate方法中,以便沒有辦法在不保存的情況下退出應用程序。 applicationWillResignActive和applicationWillTerminate應該涵蓋您的所有需求。

除了正確的錯誤處理和日誌記錄應該讓你有很多的理由。我個人喜歡將這些類型的錯誤記錄到可以根據請求發送給我的文件中。但是這對您的特定應用程序可能是過度的。這是從內存寫入,所以原諒任何錯誤。

NSError *error = nil; 
if (![[self managedObjectContext] save:&error]) 
{ 
    NSString *errorString = @"%@ ERROR : %@ %@", [[NSDate date] description], [error localizedDescription], [error userInfo]); 

    NSString *documentsDirectory = [NSHomeDirectory() 
            stringByAppendingPathComponent:@"Documents"]; 

    NSString *filePath = [documentsDirectory 
          stringByAppendingPathComponent:@"errorLog.txt"]; 

    // Write to the file 
    [errorString writeToFile:filePath atomically:YES 
      encoding:NSUTF8StringEncoding error:&error]; 
} 
1

您應該檢查是否​​方法報告的任何錯誤,例如像這樣:

NSError *error = nil; 
if (![[self managedObjectContext] save:&error]) 
{ 
    NSLog(@"Error %@", action, [error localizedDescription]);  
    NSArray* detailedErrors = [[error userInfo] objectForKey:NSDetailedErrorsKey]; 
    // if there is a detailed errors - we can dump all of them 
    if(detailedErrors != nil && [detailedErrors count] > 0) { 
     for(NSError* detailedError in detailedErrors) { 
      NSLog(@" DetailedError: %@", [detailedError localizedDescription]); 
     } 
    } 
    else { // in other case lets dump all the info we have about the error 
     NSLog(@" %@", [error userInfo]); 
    } 
} 

其中最常見的失敗原因是驗證錯誤,例如,可能期望在用戶未輸入字段時顯示字段,或者可能期望值小於XX字符等等。

基本上,這意味着如果爲客戶端提供帶有調試信息的新版本需要太長時間,則可以要求他們向您發送用於輸入數據的示例。

1

我不能確定這是什麼原因,但可能是因爲某些原因,當應用程序轉到後臺時,有時會超出處理此最大允許時間(backgroundTimeRemaining)的時間。從Apple文檔:

此屬性包含應用程序必須在後臺運行的時間量,然後纔可能被系統強行終止。當應用程序在前臺運行時,此屬性中的值保持適當的大。如果應用程序使用beginBackgroundTaskWithExpirationHandler:方法啓動一個或多個長時間運行的任務,然後轉換到後臺,則會調整此屬性的值以反映應用程序運行的時間量。

如果您的應用因爲保存上下文耗時過長而死亡,Core Data可能會決定恢復之前的狀態以至少獲得一致的結果。如果您可以從報告此問題的某些用戶那裏獲得日誌結果,則可以在嘗試保存上下文後嘗試記錄屬性值,以檢查此問題。

+0

正如我在問題中提到的那樣,每當創建新實體時都會保存託管對象上下文,所以我相當肯定這不是問題的原因。感謝您的回答。 –