[英]Enable / disable iCloud sync of Core Data while app is running
如何為Core Data(iOS7)添加啟用和禁用iCloud同步的選項?
以下是我的想法/嘗試:
要禁用iCloud同步:
NSDictionary *options = @{NSPersistentStoreUbiquitousContentNameKey: @"MYStore"};
[NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:storeUrl options:options error:&error];
但是,我認為這可能會刪除iCloud中的所有數據? 我不希望這樣。
要啟用iCloud同步:
NSDictionary *options = @{NSPersistentStoreUbiquitousContentNameKey: @"MYStore"};
[__persistentStoreCoordinator lock];
result = [__persistentStoreCoordinator migratePersistentStore:result toURL:storeUrl options:options withType:NSSQLiteStoreType error:&error];
[__persistentStoreCoordinator unlock];
在此代碼中,我嘗試使用NSPersistentStoreUbiquitousContentNameKey
鍵添加options
,以便它開始與iCloud同步。 但是,我不想將商店移到新的位置。 這段代碼合適嗎?
如何在應用程序運行時啟用/禁用iCloud?
以下是我用來啟用或禁用iCloud同步(OS X)的方法,實際上每次都會重建商店,這與在應用程序運行時啟用和禁用iCloud同步不同。 因此,您不希望將此用於“暫停”同步。
據我所知,你想要的東西如下:
如果您在應用程序運行時關閉了iCloud同步,然后執行了一些更新,則不希望這些更改同步,但稍后當您重新啟用iCloud同步時,您希望同步后續更改。
我可能錯了,但我認為使用標准的Core Data / iCloud集成可能會讓你失望。
根據您的要求,您可能只是觀察導入通知並放棄任何更改 - 但我看不出您將如何最終導致可能導致后續導入失敗的各種數據不一致。
// Removes the current Document from iCloud and deletes the local copy.
// There does not appear to be any way of only removing ubiquitous content
// and turning off iCloud sync.
// So before we remove it we make a local copy by appending "_Backup" to the filename
// (we should check this filename does not already exist and add a counter or something)
//
- (void)removeMeFromICloud {
//LOG(@"removeMeFromICloud called");
NSError *error;
NSURL *currentURL = self.fileURL;
NSString *fileType = self.fileType;
NSString *extension = [currentURL pathExtension];
NSString *path = [[currentURL URLByDeletingPathExtension] path];
NSString *backupFilename = [NSString stringWithFormat:@"%@_Backup", path];
NSURL *backupFileURL = [[[NSURL alloc] initFileURLWithPath:backupFilename] URLByAppendingPathExtension:extension];
// We only have one store
NSPersistentStore *currentStore = [self.managedObjectContext.persistentStoreCoordinator.persistentStores objectAtIndex:0];
NSDictionary *currentOptions = currentStore.options;
if ([self buildNewStoreAtURL:backupFileURL type:fileType error:&error]) {
//FLOG(@" reset the moc...");
[self.managedObjectContext reset];
[self.managedObjectContext save:&error];
//Set the document title
//FLOG(@" current displayName is %@", self.displayName);
self.fileURL = backupFileURL;
//set the file extension hidden attribute to YES
NSDictionary* fileAttrs = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]
forKey:NSFileExtensionHidden];
if(![[NSFileManager defaultManager] setAttributes:fileAttrs
ofItemAtPath:[backupFileURL path]
error:&error])
FLOG(@" unable to set file attributes to hide extension");
// Now remove the old one
bool success = [NSPersistentStoreCoordinator removeUbiquitousContentAndPersistentStoreAtURL:currentURL options:currentOptions error:&error];
if (success) {
FLOG(@" removed document from iCloud");
FLOG(@" using backup copy");
}
else {
FLOG(@" error removing document from iCloud");
FLOG(@" error is %@, %@", error, error.userInfo);
}
} else {
FLOG(@" error creating backup before removing from iCloud");
FLOG(@" error is %@, %@", error, error.userInfo);
}
}
// in order to migrate to the cloud we have to build the database from scratch,
// we can't just open it with iCloud parameters because we have to ensure that
// log files get generated in iCloud that will allow the store to be rebuilt from
// scratch by peer devices.
//
- (void)migrateMeToICloud {
//LOG(@"migrateMeToICloud called");
NSPersistentStoreCoordinator *psc = self.managedObjectContext.persistentStoreCoordinator;
NSArray *stores = psc.persistentStores;
NSError *error;
// Now get current URL and add_iCloud to the document name, use this for the new store name
NSURL *currentURL = self.fileURL;
NSString *extension = [self.fileURL pathExtension];
NSString *currentFilePathName = [[currentURL URLByDeletingPathExtension] path];
NSString *uuidString = [[NSUUID UUID] UUIDString];
NSString *newFilePathName = [NSString stringWithFormat:@"%@_UUID_%@",currentFilePathName, uuidString];
// We must make it NSSQLite so get the right extension...
NSURL *newURL = [[[NSURL alloc] initFileURLWithPath:newFilePathName] URLByAppendingPathExtension:extension];
NSDictionary *options = [self storeOptionsForICloud:self.fileURL];
NSString *ubiquityName = [options valueForKey:NSPersistentStoreUbiquitousContentNameKey];
if ([stores count]) {
NSPersistentStore *store = [stores objectAtIndex:0];
if (store) {
//FLOG(@" starting migration...");
NSPersistentStore *newStore = [psc migratePersistentStore:store toURL:newURL options:options withType:NSSQLiteStoreType error:&error];
//FLOG(@" psc is %@", psc);
//FLOG(@" done migrating...");
if (newStore != nil) {
//FLOG(@" new store seems OK...");
// Set custom metadata so we know if it is synced in iCloud next time we open it
[self setiCloudMetaDataForStore:currentURL ofType:NSSQLiteStoreType iCloud:YES ubiquityName:ubiquityName];
}
else {
FLOG(@" error migrating store");
FLOG(@" error is %@, %@", error, error.userInfo);
}
} else {
FLOG(@" store is nil, nothing to migrate!");
}
}
}
// File is NEVER iCloud enabled when we do this.
// Is we do Save As we pnly build a local store wihout iCloud sync.
// User can select iCloud sync once Save As is done
//
- (bool)buildNewStoreAtURL:(NSURL*)newURL type:(NSString *)typeName error:(NSError **)error {
//FLOG(@"buildNewStoreAtURL:type: called");
NSError *myError;
// We only have one store
NSPersistentStore *currentStore = [self.managedObjectContext.persistentStoreCoordinator.persistentStores objectAtIndex:0];
NSDictionary *currentOptions = currentStore.options;
// We usually would need to create a new UUID for the new document if it is in iCloud.
// But since we create a local copy only we don't need this.
NSMutableDictionary *newOptions = [[NSMutableDictionary alloc] initWithDictionary:currentOptions];
[newOptions setObject:@"DELETE" forKey:@"JOURNAL"];
// Remove any iCloud options (this one includes the unique iCloud UUID
[newOptions removeObjectForKey:NSPersistentStoreUbiquitousContentNameKey];
// Remove Core Data ubiquity metadata
[newOptions setObject:[NSNumber numberWithBool:YES] forKey:NSPersistentStoreRemoveUbiquitousMetadataOption];
NSPersistentStoreCoordinator *psc = self.managedObjectContext.persistentStoreCoordinator;
// Now migrate the store to the new location
NSPersistentStore *newStore = [psc migratePersistentStore:currentStore toURL:newURL options:newOptions withType:typeName error:&myError];
if (newStore) {
// Now set up our custom metadata so we can determine if it has been synced in iCloud next time we open it
NSDictionary *dict = [self getiCloudMetaDataForStore:[psc metadataForPersistentStore:newStore] iCloud:NO ubiquityName:nil];
[psc setMetadata:dict forPersistentStore:newStore];
return YES;
}
else {
FLOG(@" problem creating new document");
FLOG(@" - error is %@, %@", myError, myError.userInfo);
*error = myError;
return NO;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.