我正在開發iOS 7應用程序,我對iCloud和Core數據相當陌生。 我的假設是用戶總是希望儘可能使用iCloud for Backup。這就是爲什麼我建立了我的持久性存儲如下:iCloud核心數據遷移
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSURL *storeURL = [[[self applicationDocumentsDirectory]
URLByAppendingPathComponent:storeNameWithoutFileExtension isDirectory:NO]
URLByAppendingPathExtension:@"sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(persistentStoreDidImportUbiquitiousContentChanges:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:__persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(storesWillChange:)
name:NSPersistentStoreCoordinatorStoresWillChangeNotification
object:__persistentStoreCoordinator];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(storesDidChange:)
name:NSPersistentStoreCoordinatorStoresDidChangeNotification
object:__persistentStoreCoordinator];
NSDictionary *options = @{ NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentNameKey : storeNameWithoutFileExtension, };
// NSPersistentStoreRebuildFromUbiquitousContentOption
// NSMigratePersistentStoresAutomaticallyOption: @YES,
// NSMigratePersistentStoresAutomaticallyOption : @YES,
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
在此設置下,我總是立即開始使用下文檔的文件夾/ CoreDataUbiquitySupport即使用戶沒有登錄到iCloud(使用「本地」文件夾) 。
正如您所看到的,我正在註冊通知。
- 爲什麼在鍵NSAddedPersistentStoresKey和NSRemovedPersistentStoresKey在NSPersistentStoreCoordinatorStoresWillChangeNotification和NSPersistentStoreCoordinatorStoresDidChangeNotification總是相同的例如的NSNotifications的陣列中的添加和刪除的持久性存儲爲案例帳戶添加? 人們會期望通知包含已刪除的持久性存儲和新添加的。所以他們不應該是一樣的。但不幸的是他們總是一樣的。
當前的行爲是,如果我切換帳戶或註銷帳戶或登錄到新帳戶,則應用程序始終從關聯的商店開始,如果以前沒有開始,則新的應用程序開始。我希望的行爲是應用程序總是將數據遷移到新的商店。例如:用戶未登錄到iCloud並開始使用我的應用程序。他在Documents/CoreDataUbiquitySupport中創建保存在本地下的數據。現在他打開了iCloud。現在我想將本地數據遷移到雲端。目前這沒有發生。 我需要在哪種方法中實現遷移,以及我如何實現它?我可以使用方法「migratePersistentStore」嗎?我試着用下面的代碼在NSPersistentStoreCoordinatorStoresDidChangeNotification但無濟於事:
- (void)storesDidChange:(NSNotification *)n {
// refresh user interface
switch ([[n.userInfo objectForKey:NSPersistentStoreUbiquitousTransitionTypeKey] integerValue]) {
case NSPersistentStoreUbiquitousTransitionTypeAccountAdded : {
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeAccountAdded migrate");
NSError *error = nil;
NSURL *storeURL = ((NSPersistentStore *)asdf[0]).URL;
NSDictionary *options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentNameKey : storeNameWithoutFileExtension, };
NSPersistentStore *asdfasdf = [__persistentStoreCoordinator migratePersistentStore:self.oldStore toURL:storeURL options:options withType:NSSQLiteStoreType error:&error];
}
break;
case NSPersistentStoreUbiquitousTransitionTypeAccountRemoved :
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeAccountRemoved");
break;
case NSPersistentStoreUbiquitousTransitionTypeContentRemoved : {
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeContentRemoved migrate");
NSError *error = nil;
NSURL *storeURL = ((NSPersistentStore *)asdf[0]).URL;
NSDictionary *options = @{ NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentNameKey : storeNameWithoutFileExtension, };
NSPersistentStore *asdfasdf = [__persistentStoreCoordinator migratePersistentStore:self.oldStore toURL:storeURL options:options withType:NSSQLiteStoreType error:&error];
}
break;
case NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted :
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted");
NSLog(@"initial import");
break;
default :
break;
}
}
變量oldStore是在NSPersistentStoreCoordinatorStoresWillChangeNotification設置,因爲我不能依靠NSNotification及其鍵NSAddedPersistentStoresKey和NSRemovedPersistentStoresKey因爲此前兩國都陣列始終包含與前述相同的商店。
在哪種方法中/在什麼時候我會執行重複數據刪除代碼?我可以在其中一個通知中完成嗎?
對於哪個用例,我必須使用NSMigratePersistentStoresAutomaticallyOption?這個選項如何工作?
我在使用我的應用程序時遇到的奇怪行爲是,如果用戶未登錄到iCloud。當我將應用程序置於後臺並退出iCloud並返回到我的應用程序時,我得到的NSNotifications類型爲NSPersistentStoreUbiquitousTransitionTypeContentRemoved。我期望NSPersistentStoreUbiquitousTransitionTypeAccountRemoved。如果我然後將該應用程序置於後臺並再次備份,則會獲取類型爲NSPersistentStoreUbiquitousTransitionTypeAccountRemoved的NSNotifications。但不幸的是,當用戶未登錄到iCloud並且應用程序正在運行並且用戶將該應用程序置於後臺並返回前臺時,NSPersistentCoordinatorStoresWillChangeNotification和NSPersistentStoreCoordinatorStoresDidChangeNotification將始終爲用例觸發,並且我得到類型爲NSPersistentStoreUbiquitousTransitionTypeAccountRemoved的NSNotifications。這總是發生。 - 爲什麼?
爲了使我使用的代碼完成,這裏是我的NSPersistentStoreCoordinatorStoresWillChangeNotification和NSPersistentStoreDidImportUbiquitousContentChangesNotification和一對夫婦等功能代碼:
- (void)storesWillChange:(NSNotification *)n {
NSLog(@"storesWillChange");
NSArray *pStores = self.persistentStoreCoordinator.persistentStores;
NSManagedObjectContext *moc = [self managedObjectContext];
switch ([[n.userInfo objectForKey:NSPersistentStoreUbiquitousTransitionTypeKey] integerValue]) {
case NSPersistentStoreUbiquitousTransitionTypeAccountAdded : {
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeAccountAdded");
self.oldStore = pStores[0];
}
break;
case NSPersistentStoreUbiquitousTransitionTypeAccountRemoved :
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeAccountRemoved");
break;
case NSPersistentStoreUbiquitousTransitionTypeContentRemoved :
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeContentRemoved");
self.oldStore = pStores[0];
break;
case NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted :
NSLog(@"NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted");
NSLog(@"initial import");
break;
default :
break;
}
[moc performBlockAndWait:^{
NSError *error = nil;
if ([moc hasChanges]) {
[moc save:&error];
}
[moc reset];
}];
// reset user interface
}
- (void)persistentStoreDidImportUbiquitiousContentChanges:(NSNotification *)changeNotification {
NSLog(@"*** Incoming iCloud Data ***");
NSManagedObjectContext *moc = [self managedObjectContext];
[moc performBlock:^{
[moc mergeChangesFromContextDidSaveNotification:changeNotification];
}];
}
- (NSManagedObjectContext *)managedObjectContext {
if (__managedObjectContext != nil) {
return __managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
__managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
// __managedObjectContext = [[NSManagedObjectContext alloc] init];
[__managedObjectContext setPersistentStoreCoordinator:coordinator];
[__managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
}
return __managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:dataModelName withExtension:@"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
所以基本上我要完成的是用戶有相同的數據,無論哪個iCloud帳戶即使是「本地」也在使用。
任何幫助,將不勝感激。先謝謝你!
查看此鏈接,瞭解示例代碼和視頻,演示用戶更改其iCloud設置時iCloud同步和存儲遷移。 http://ossh.com.au/design-and-technology/software-development/ –