2014-02-12 90 views
0

遷移在模擬器上正常工作。但是,在設備上,我看不到任何錯誤消息,但遷移的商店是空的。將iCloud商店遷移到本地

NSDictionary *iCloudOptions = @{ 
    NSPersistentStoreUbiquitousContentNameKey : @"iCloudNimbleStore", 
    NSPersistentStoreUbiquitousContentURLKey : @"transactions_logs", 
    NSMigratePersistentStoresAutomaticallyOption : @YES, 
    NSInferMappingModelAutomaticallyOption : @YES 
}; 
NSDictionary *localOptions = @{NSMigratePersistentStoresAutomaticallyOption : @YES, 
    NSInferMappingModelAutomaticallyOption : @YES 
}; 
if (![[NSFileManager defaultManager]fileExistsAtPath:self.storeURL.path]) { 
    @synchronized(@"Migration") 
    { 
     // thread-safe code 
     if ([[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]) { 
      NSLog(@"iCloud"); 
      [self migrateStoreFromURL:[self nb_URLToStoreWithFilename:[self nb_appName]]options:iCloudOptions]; 
     }else{ 
      [self migrateStoreFromURL:[self nb_URLToStoreWithFilename:[NSString stringWithFormat:@"%@.sqlite", [self nb_appName]]] options:localOptions]; 
      // 
      [self migrateStoreFromURL:[self nb_URLToOldStoreWithFilename] options:localOptions]; 
     } 
    } 
} 

NSDictionary *options = @{ 
    NSMigratePersistentStoresAutomaticallyOption:@YES 
    ,NSInferMappingModelAutomaticallyOption:@YES 
}; 
NSError *error = nil; 
[_coordinator lock]; 
_store = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self storeURL] options:options error:&error]; 
[_coordinator unlock]; 
if (!_store) { 
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Loading Fail" message:[NSString stringWithFormat:@"Failed to add store. Error: %@", error] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
    [alert show]; 
    NSLog(@"Failed to add store. Error: %@", error);abort(); 
} else { 
    UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Loading Success" message:[NSString stringWithFormat:@"Successfully added store: %@", _store] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
    [alert show]; 
    NSLog(@"Successfully added store: %@", _store); 
    if (_store && !error) { 
     // Encrypt the password database 
     NSError *encrError; 
     NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey]; 
     if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:self.storeURL.path error:&encrError]){ 
      NSLog(@"Unresolved error with password store encryption %@, %@", encrError, [encrError userInfo]); 
      abort(); 
     }else {NSLog(@"Encrypted");} 
    } 
} 

下面是遷移過程:

- (void)migrateStoreFromURL:(NSURL *)oldStoreURL options:(NSDictionary *)oldOptions{ 
if (debug==1) { 
    TFLog(@"Running %@ '%@'", self.class, NSStringFromSelector(_cmd)); 
} 
if (_store) 
{ 
    NSLog(@"NOT NEEDED"); 
    return; 
} 

UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Migration" message:[NSString stringWithFormat:@"Found old store at %@",oldStoreURL.path] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
[alert show]; 

NSFileManager *fileManager = [NSFileManager defaultManager]; 

if (![fileManager fileExistsAtPath:self.storeURL.path]) { 
    NSDictionary *options = 
    @{ 
     NSMigratePersistentStoresAutomaticallyOption:@YES 
     ,NSInferMappingModelAutomaticallyOption:@YES 
     }; 
    NSError *error = nil; 
    [_coordinator lock]; 
    NSPersistentStore *srcPS = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType 
                        configuration:nil 
                          URL:oldStoreURL 
                         options:oldOptions 
                          error:&error]; 

    _store = [_coordinator migratePersistentStore:srcPS 
                      toURL:self.storeURL 
                      options:options 
                      withType:NSSQLiteStoreType 
                      error:&error]; 
    [_coordinator unlock]; 
    if (_store && !error) { 
     UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Migration Success" message:[NSString stringWithFormat:@"Old store successfully migrated from %@",oldStoreURL.path] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     [alert show]; 
     // Encrypt the password database 
     NSError *encrError; 
     NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey]; 
     if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:self.storeURL.path error:&encrError]){ 
      UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Encryption Error" message:[NSString stringWithFormat:@"Unresolved error with password store encryption %@, %@", encrError, [encrError userInfo]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
      [alert show]; 
     } 

    }else{ 
     UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Migration Error" message:error.localizedDescription delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     [alert show]; 
    } 

} 

UPD:我檢查了新遷移的商店的大小和它的0最詭異的是_store && !error是真實的。我也嘗試將NSPersistentStoreRemoveUbiquitousMetadataOption: @YES添加到遷移選項,但它不會改變任何內容。

Upd。 2我認爲在一個設備上iCloud商店的URL在其加載前是零。我需要一些解決方法來等待,直到完成。

+0

您是否等待足夠長的遷移完成?打開核心數據記錄並監控Xcode中的iCloud網絡流量以查看發生了什麼。 –

+0

不,我沒在等。問題是,在設備上我遷移後得到空的存儲。在啓用iCloud的模擬器上一切順利。從TestFlight安裝更新時,我無法使用日誌記錄。 – Shmidt

回答

1

我不是100%確定的,我明白你正在嘗試做什麼與遷移。通常會將數據植入空白商店進行遷移,但看起來您正試圖將數據從iCloud遷移到本地商店。是對的嗎?你不應該這樣做。 iCloud應自動將其他設備的數據添加到您的商店。

該行還沒有看的權利:

NSPersistentStoreUbiquitousContentURLKey : @"transactions_logs", 

我想你想使用URL有指向的iCloud容器內的事務日誌目錄。例如。

NSURL *containerURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]; 
NSURL *url = [containerURL URLByAppendingPathComponent:@"transactions_logs"]; 

在使用iCloud時,重要的是要意識到數據不會瞬間傳輸。可能需要一段時間才能到達,並且您的應用程序無法確切知道是否有數據傳入。您可以使用元數據查詢來監視元數據,但即使這種情況經常會在其他設備上的數據已經生成之後到達。

因此,簡單地在無處不在容器中尋找數據並不會有多大幫助,因爲可能有或沒有數據可用。你只是不知道,你必須在考慮到這個假設的情況下開發你的方法,以便它能夠處理任何延遲。

獲得iCloud同步處理核心數據所需的遷移是混亂和不必要的。你可能更有可能使用自動完成這些工作的框架,比如Core Data Ensembles,讓事情運行良好。 (披露:我是Ensembles的開發人員。)

+0

我試圖用您的線替換內容網址,但它沒有幫助。自iOS7以來,這條線是完全有效的(它是在WWDC2013,Core Data和iCloud講座中介紹的)。我使用了Nimble框架,這是專門爲使用iOS7 iCloud同步優勢而編寫的,但它在數據模型版本控制方面有問題,所以我決定將商店遷移到本地。遷移工作正常,當在Xcode中測試時,但是當我在iPad上測試時,它會創建0大小的文件而不會出現任何錯誤... – Shmidt

+0

您確定遷移的文件實際上是空的嗎?你如何測試?您正在查看商店文件大小,還是從商店獲取對象?我問的原因是,使用新的日誌功能,如果緩衝數據未達到特定級別,則sqlite存儲可以保持爲空。 –

+0

是的,我使用AlertView進行測試,當通過TestFlight安裝時,它是零。就在一分鐘前,我決定檢查應用程序的以前版本,當我通過TestFlight發送它時,它的商店也是零。所以這個遷移似乎沒有錯,但TestFlight更新開始刪除文檔數據。前段時間我改變了配置文件,也許這就是原因。 – Shmidt