2013-02-26 115 views
0

我試圖用NSManagedDocument構建一種在覈心數據中保存數據的現代方法。一切正常,只是如果我重新啓動應用程序(終止並再次運行它)我會重複我的數據庫實體,有時應用程序崩潰與錯誤:核心數據中的重複項

This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.

我覺得有東西在回事不同的線程和麻煩,但我無法弄清楚我必須改變。希望你們中的一個能幫助我。

我叫Database類有此實現

+ (Database *)sharedDatabase 
{ 
static Database *sharedInstance; 
static dispatch_once_t oncePredicate; 
dispatch_once(&oncePredicate, ^{ 
    NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
    url = [url URLByAppendingPathComponent:@"Default Database"]; 
    sharedInstance = [[self alloc] initWithFileURL:url]; 
    sharedInstance.isCreating = NO; 
    sharedInstance.isOpening = NO; 
}); 
if (![[NSFileManager defaultManager] fileExistsAtPath:[sharedInstance.fileURL path]]) { 
    if (!sharedInstance.isCreating) { 
     sharedInstance.isCreating = YES; 
     [sharedInstance saveToURL:sharedInstance.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) { 
      sharedInstance.isCreating = NO; 
     }]; 
    } 
} else if(sharedInstance.documentState == UIDocumentStateClosed){ 
    if (!sharedInstance.isOpening) { 
     sharedInstance.isOpening = YES; 
     [sharedInstance openWithCompletionHandler:^(BOOL success) { 
      sharedInstance.isOpening = NO; 
     }]; 
    } 
} 
return sharedInstance; 
} 

,我已經創建了一個實體的數據模型稱爲Book。爲了保持簡單,它只有一個isbn(類型NSString)作爲屬性。 類CreateNSManagedObject子類Book(Xcode自動生成的子類)具有以下實現來檢查數據庫中是否已存在ISBN。這應該返回一個新創建的實體或現有的實體,並且在發生一些錯誤時返回nil,例如有兩本ISBN相同的書。

+(Book *) bookWithISBN:(NSString *)isbn inManagedObjectContext:(NSManagedObjectContext *)context 
{ 
Book *book; 

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Book"]; 
request.predicate = [NSPredicate predicateWithFormat:@"isbn LIKE %@", isbn]; 
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"isbn" ascending:YES]; 
request.sortDescriptors = @[sortDescriptor]; 

NSError *error; 
NSArray *matches = [context executeFetchRequest:request error:&error]; 
if (!matches || (matches.count > 1)) { 
    return nil; 
} else if(matches.count == 0){ 
    book = [NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:context]; 
    book.isbn = isbn; 
}else{ 
    book = [matches lastObject]; 
} 
return book; 
} 

所以,現在,如果我調用通過調用[Book bookWithISBN:@"1234567890" inManagedObjectContext:[Database sharedDatabase].managedObjectContext]我第一次運行會造成我的數據庫中的實體應用此方法。如果我終止應用並再次運行它,則會再次創建相同的實體。第二次終止並再次運行它會返回nil(因爲有2本書有相同的ISBN)。

我在這個項目中使用ARC。

可能的解決辦法

我一直在嘗試幾個小時現在,直到現在看來,如果我不繼承UIManagedDocument,而是使從NSObject繼承幷包含一個UIManagedDocument一類的工作。有人知道是否真的是正確的解決方案?因爲我認爲應該可以繼承UIManagedDocument

+0

我想我自己找到了解決方案。如果我在設置請求謂詞時使用LIKE替換=它在我的示例中起作用。我會在我真實的應用程序中測試它,這個應用程序要複雜得多,並會在明天做出響應。我只是不明白爲什麼'='會在第二次'重新運行'的情況下正常工作 – Bohrnsen 2013-02-26 23:35:41

+0

您最初是否使用過「=」或「==」? – sosborn 2013-02-26 23:41:42

+0

我最初使用單個'=' – Bohrnsen 2013-02-26 23:46:28

回答

1

這個建議並不能解決立即解決問題,但我會把它放在那裏呢。我曾經像你一樣以原始形式使用coreData,直到我發現了MagicalRecord。太棒了。你應該檢查一下。 https://github.com/magicalpanda/MagicalRecord

好處是它將所有CoreData代碼打包成易於理解的代碼。它負責管理線程中的上下文關係。

+0

謝謝。我會試一試 – Bohrnsen 2013-02-27 09:54:26

+0

這非常簡單,完全沒有學習曲線。 – 2013-02-27 09:56:30

+0

我實際上是在一年前或更早的時候嘗試過這一點,並認爲這確實很複雜,但也許今天我對所有術語有了更好的理解 – Bohrnsen 2013-02-27 10:03:38