iOS 7 iCloud 和(启用/禁用)Core Data - 永无止境的故事
Posted
技术标签:
【中文标题】iOS 7 iCloud 和(启用/禁用)Core Data - 永无止境的故事【英文标题】:iOS 7 iCloud & (enable/disable) Core Data - The never ending story 【发布时间】:2014-03-07 22:52:07 【问题描述】:目前我尝试使用 CoreData 建立 iCloud。我的应用“仅”基于 ios 7,因此启用 iCloud 非常容易。基础工作非常好(保存到 iCloud)。我现在搜索了两个多星期,但我没有找到解决我的问题的方法。
我的问题: 如果用户在设置中启用/禁用 iCloud 或更改 iCloud 帐户,我的应用程序应该以两种方式合并更改。 所以这是我的场景:
应用启动 -> iCloud 关闭 -> 数据已保存(本地) -> 用户打开 iCloud -> 本地数据将合并到 iCloud
应用启动 -> iCloud 开启 -> 数据已保存 (iCloud) -> 用户关闭 iCloud -> iCloud 数据将合并到本地
在许多其他线程中,一些开发人员写道,只有一个具有相同选项和 url 的持久存储就足够了,因为 iOS 7 核心数据在禁用 iCloud 时处理自动回退存储,如果可用则触发合并再次。但这对我不起作用。
这里有一些代码sn-ps:
- (NSURL*)storeURL
NSURL* documentsDirectory = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:NULL];
return [documentsDirectory URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.sqlite",coreDataFileName]];
- (NSURL*)modelURL
return [[NSBundle mainBundle] URLForResource:coreDataFileName withExtension:@"momd"];
-(NSMutableDictionary*)getICloudPersistentStoreOptions
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:
NSInferMappingModelAutomaticallyOption];
//if(self.hasICloudAccountOnDevice & self.iCloudLokalIsAvailable)
[options setObject:@"iCloudStore" forKey:NSPersistentStoreUbiquitousContentNameKey];
//
return options;
- (NSManagedObjectContext *)managedObjectContext
if (masterContext != nil)
return masterContext;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil)
masterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
masterContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
[masterContext setPersistentStoreCoordinator: coordinator];
return masterContext;
- (NSManagedObjectModel *)managedObjectModel
if (managedObjectModel != nil)
return managedObjectModel;
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL];
return managedObjectModel;
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
if((persistentStoreCoordinator != nil))
return persistentStoreCoordinator;
[self createPersistentStoreCoordinator];
return persistentStoreCoordinator;
-(void)createPersistentStoreCoordinator
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSPersistentStoreCoordinator *psc = persistentStoreCoordinator;
// iCloud notification subscriptions
NSNotificationCenter *dc = [NSNotificationCenter defaultCenter];
[dc addObserver:self
selector:@selector(storesWillChange:)
name:NSPersistentStoreCoordinatorStoresWillChangeNotification
object:psc];
[dc addObserver:self
selector:@selector(storesDidChange:)
name:NSPersistentStoreCoordinatorStoresDidChangeNotification
object:psc];
[dc addObserver:self
selector:@selector(persistentStoreDidImportUbiquitousContentChanges:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:psc];
// Set up iCloud persistent store in another thread:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
NSError* error;
[psc lock];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:self.storeURL
options:[self getICloudPersistentStoreOptions]
error:&error];
[psc unlock];
);
在“storeWillChange”方法中,我想在 NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted 之后实现一些重复数据删除代码,但那是另一回事。
NSPersistentStoreDidImportUbiquitousContentChangesNotification 当前未使用(我认为只有在其他设备也将一些数据保存到 iCloud 时才会调用它 .
每次应用启动时都会调用来自 NSPersistentStoreCoordinatorStoresDidChangeNotification 的“storeDidChange”。所以目前我不知道我应该在那里做什么。
正如我之前写的那样,这对我不起作用,如果我启用或禁用 iCloud,数据将不会被合并。
请帮助我 - 我的想法错了吗??
【问题讨论】:
我看过一个 Duncan 的网站,它很棒,但我的脑子里有些过头了。我正要放弃,发现了这个,github.com/mluisbrown/iCloudCoreDataStack 【参考方案1】:看看这里,我对这些问题做了一些注释。 http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/sample-apps-explanations/
还可以查看处理 iCloud 帐户转换的示例应用程序,我认为您可以在需要转换并且目标商店已经存在时选择合并选项。
请注意,如果用户在 iCloud 开启时选择使用本地存储,则会删除 iCloud 存储。也不是说在 iCloud 关闭后没有尝试迁移 iCloud 商店。根据 Apple 的说法,一旦用户退出 iCloud,您就不能依赖 iCloud 商店。
【讨论】:
谢谢!这有很大帮助。它真的很棒!我可以将 OSCDStackManager 的修改版本用于私人和商业用途吗?但无论如何,OSCDStackManager 中存在一些问题。我们可以在这里讨论这个吗? 当然可以使用它,如果您认为需要解决的问题或您对它的工作方式/原因有疑问,请在网站上向我发送消息,我将不胜感激。 @Duncan - 如果您可以在示例代码中添加更多 cmets 等,那就太好了。以它目前的状态,我没有信心,也不知道使用它的好方法......只是我的意见 是的,我知道,我在一周左右的时间内将它一起破解,作为生产应用程序的概念证明,因此它并不是真正的教程。必须写一本书才能涵盖所有方面! @user2075873 我一直没有收到电子邮件,请再次尝试发送至 ducan.groenewald@ossh.com.au。【参考方案2】:有两种方法可以做到这一点:
-
将实体从一个商店深度复制到另一个商店;
将商店从本地迁移到 iCloud,反之亦然。
由于代码较少,第二种方式更容易。
【讨论】:
以上是关于iOS 7 iCloud 和(启用/禁用)Core Data - 永无止境的故事的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 7 中禁用 Core Data 中的 iCloud(也就是将持久存储文件迁移到本地)