iOS 11+ 如何将现有的核心数据迁移到共享应用组以用于扩展?
iOS 11+ How to migrate existing Core Data to Shared App Group for use in extension?
当我使用核心数据模板创建 iOS 11 应用程序时,它会自动在 AppDelete.m 中生成以下代码。
synthesize persistentContainer = _persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"My_History"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
我想添加一个 Today 和 iMessage 扩展来访问核心数据中的历史记录。根据我的阅读,我需要将这些数据(如果存在)迁移到共享的应用程序容器中。我该怎么做?
代码在objective C.
我读过其他涉及此的问题,但所有这些问题似乎都是在 Apple 更改核心数据的工作方式以使其更容易之前发生的。正如您在我的代码中看到的,我从未指定数据存储的确切文件名是什么。我看到的每个例子都有类似 "My_History.sqllite" 的东西。我什至不知道我的是不是 sql 精简版数据库,它只是由该代码创建的。
更新:
要迁移现有的持久存储,NSPersistentContainer
包含 persistentStoreCoordinator
,NSPersistentStoreCoordinator
的一个实例。这公开了迁移持久存储的方法 migratePersistentStore:toURL:options:withType:error:
。
我会做以下事情:
// Get the reference to the persistent store coordinator
let coordinator = persistentContainer.persistentStoreCoordinator
// Get the URL of the persistent store
let oldURL = persistentContainer.persistentStoreDescriptions.url
// Get the URL of the new App Group location
let newURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("YOUR_APP_GROUP")
// Get the reference to the current persistent store
let oldStore = coordinator.persistentStore(for: oldURL)
// Migrate the persistent store
do {
try coordinator.migratePersistentStore(oldStore, to: newURL, options: nil, withType: NSSQLiteStoreType)
} catch {
// ERROR
}
请注意,以上内容尚未经过测试,我也没有处理过 Optionals,因此并不完整。另外,对于它在 Swift 中,我深表歉意。希望您可以很容易地在 Objective-C.
中编写等效项
原文:
下面概述了如何在非默认位置创建一个 NSPersistentContainer
到持久存储的接口。
NSPersistentContainer
公开了 defaultDirectoryURL
,并指出:
This method returns a platform-dependent NSURL
at which the persistent
store(s) will be located or are currently located. This method can be
overridden in a subclass of NSPersistentContainer
.
如果您继承 NSPersistentContainer
并使用 containerURLForSecurityApplicationGroupIdentifier
将 defaultDirectoryURL
定义为 App Group 目录,那么您应该能够访问您的应用程序和扩展之间的容器(假设它们具有相同的应用程序组权利)。
NSPersistentContainer
还公开了 persistentStoreDescriptions
,它还具有一个 URL 实例。同样,您可以在调用 loadPersistentStoresWithCompletionHandler:
.
之前将此更新到应用程序组 URL
请注意,我没有使用过 NSPersistentContainer
,不知道这种共享是否会导致任何并发问题。
我最终完成了以下操作。 sqlite文件其实就是我的init的名字加上最后的.sqlite
+ (NSPersistentContainer*) GetPersistentContainer {
//Init the store.
NSPersistentContainer *_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"Test_App"];
//Define the store url that is located in the shared group.
NSURL* storeURL = [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.Test_App"] URLByAppendingPathComponent:@"Test_App.sqlite"];
//Determine if we already have a store saved in the default app location.
BOOL hasDefaultAppLocation = [[NSFileManager defaultManager] fileExistsAtPath: _persistentContainer.persistentStoreDescriptions[0].URL.path];
//Check if the store needs migration.
BOOL storeNeedsMigration = hasDefaultAppLocation && ![_persistentContainer.persistentStoreDescriptions[0].URL.absoluteString isEqualToString:storeURL.absoluteString];
//Check if the store in the default location does not exist.
if (!hasDefaultAppLocation) {
//Create a description to use for the app group store.
NSPersistentStoreDescription *description = [[NSPersistentStoreDescription alloc] init];
//set the automatic properties for the store.
description.shouldMigrateStoreAutomatically = true;
description.shouldInferMappingModelAutomatically = true;
//Set the url for the store.
description.URL = storeURL;
//Replace the coordinator store description with this description.
_persistentContainer.persistentStoreDescriptions = [NSArray arrayWithObjects:description, nil];
}
//Load the store.
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
//Check that we do not have an error.
if (error == nil) {
//Check if we need to migrate the store.
if (storeNeedsMigration) {
//Create errors to track migration and deleting errors.
NSError *migrateError;
NSError *deleteError;
//Store the old location URL.
NSURL *oldStoreURL = storeDescription.URL;
//Get the store we want to migrate.
NSPersistentStore *store = [_persistentContainer.persistentStoreCoordinator persistentStoreForURL: oldStoreURL];
//Set the store options.
NSDictionary *storeOptions = @{ NSSQLitePragmasOption : @{ @"journal_mode" : @"WAL" } };
//Migrate the store.
NSPersistentStore *newStore = [_persistentContainer.persistentStoreCoordinator migratePersistentStore: store toURL:storeURL options:storeOptions withType:NSSQLiteStoreType error:&migrateError];
//Check that the store was migrated.
if (newStore && !migrateError) {
//Remove the old SQLLite database.
[[[NSFileCoordinator alloc] init] coordinateWritingItemAtURL: oldStoreURL options: NSFileCoordinatorWritingForDeleting error: &deleteError byAccessor: ^(NSURL *urlForModifying) {
//Create a remove error.
NSError *removeError;
//Delete the file.
[[NSFileManager defaultManager] removeItemAtURL: urlForModifying error: &removeError];
//If there was an error. Output it.
if (removeError) {
NSLog(@"%@", [removeError localizedDescription]);
}
}
];
//If there was an error. Output it.
if (deleteError) {
NSLog(@"%@", [deleteError localizedDescription]);
}
}
}
} else {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
//Return the container.
return _persistentContainer;
}
solidsnake4444's 拯救了我的一天。这里是 Swift 5.0 版本。
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApp")
let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.my.app")!.appendingPathComponent("MyApp.sqlite")
var defaultURL: URL?
if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
defaultURL = FileManager.default.fileExists(atPath: url.path) ? url : nil
}
if defaultURL == nil {
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
}
container.loadPersistentStores(completionHandler: { [unowned container] (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
if let url = defaultURL, url.absoluteString != storeURL.absoluteString {
let coordinator = container.persistentStoreCoordinator
if let oldStore = coordinator.persistentStore(for: url) {
do {
try coordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
} catch {
print(error.localizedDescription)
}
// delete old store
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: { url in
do {
try FileManager.default.removeItem(at: url)
} catch {
print(error.localizedDescription)
}
})
}
}
})
return container
}()
移动 NSPersistentCloudKitContainer
时,这对我有用。需要注意的几件事:
- 您需要确保
cloudKitContainerOptions
在持久存储描述中设置,否则同步将停止工作
- 不要调用
migratePersistentStore
否则你会得到重复的记录,而是使用 replacePersistentStore
- 请参阅此 thread 了解更多信息
- 您可能希望在成功迁移后删除旧数据库,
destroyPersistentStore
听起来很有希望,但似乎并没有真正删除文件 - 请参阅此 question
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "MyCuteDB")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
} else {
// Use App Groups so app and extensions can access database
let sharedStoreURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.yourdomain.yourapp")!.appendingPathComponent("\(container.name).sqlite")
let defaultStoreURL = container.persistentStoreDescriptions.first!.url! //the URL always starts out in the default location
// move database to shared location if needed
if FileManager.default.fileExists(atPath: defaultStoreURL.path) && !FileManager.default.fileExists(atPath: sharedStoreURL.path) {
let coordinator = container.persistentStoreCoordinator
do {
try coordinator.replacePersistentStore(at: sharedStoreURL, destinationOptions: nil, withPersistentStoreFrom: defaultStoreURL, sourceOptions: nil, ofType: NSSQLiteStoreType)
try? coordinator.destroyPersistentStore(at: defaultStoreURL, ofType: NSSQLiteStoreType, options: nil)
// destroyPersistentStore says it deletes the old store but seems to be a lie so we'll manually delete the files
NSFileCoordinator(filePresenter: nil).coordinate(writingItemAt: defaultStoreURL.deletingLastPathComponent(), options: .forDeleting, error: nil, byAccessor: { url in
try? FileManager.default.removeItem(at: defaultStoreURL)
try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("\(container.name).sqlite-shm"))
try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("\(container.name).sqlite-wal"))
try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("ckAssetFiles"))
})
} catch {
//TODO: Handle error
}
}
// change URL from default to shared location
if FileManager.default.fileExists(atPath: sharedStoreURL.path) {
container.persistentStoreDescriptions.first!.url = sharedStoreURL
}
}
let description = container.persistentStoreDescriptions.first!
description.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.yourdomain.yourapp")
container.loadPersistentStores { description, error in
//TODO: Handle error
}
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.automaticallyMergesChangesFromParent = true
}
}
当我使用核心数据模板创建 iOS 11 应用程序时,它会自动在 AppDelete.m 中生成以下代码。
synthesize persistentContainer = _persistentContainer;
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"My_History"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
我想添加一个 Today 和 iMessage 扩展来访问核心数据中的历史记录。根据我的阅读,我需要将这些数据(如果存在)迁移到共享的应用程序容器中。我该怎么做?
代码在objective C.
我读过其他涉及此的问题,但所有这些问题似乎都是在 Apple 更改核心数据的工作方式以使其更容易之前发生的。正如您在我的代码中看到的,我从未指定数据存储的确切文件名是什么。我看到的每个例子都有类似 "My_History.sqllite" 的东西。我什至不知道我的是不是 sql 精简版数据库,它只是由该代码创建的。
更新:
要迁移现有的持久存储,NSPersistentContainer
包含 persistentStoreCoordinator
,NSPersistentStoreCoordinator
的一个实例。这公开了迁移持久存储的方法 migratePersistentStore:toURL:options:withType:error:
。
我会做以下事情:
// Get the reference to the persistent store coordinator
let coordinator = persistentContainer.persistentStoreCoordinator
// Get the URL of the persistent store
let oldURL = persistentContainer.persistentStoreDescriptions.url
// Get the URL of the new App Group location
let newURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("YOUR_APP_GROUP")
// Get the reference to the current persistent store
let oldStore = coordinator.persistentStore(for: oldURL)
// Migrate the persistent store
do {
try coordinator.migratePersistentStore(oldStore, to: newURL, options: nil, withType: NSSQLiteStoreType)
} catch {
// ERROR
}
请注意,以上内容尚未经过测试,我也没有处理过 Optionals,因此并不完整。另外,对于它在 Swift 中,我深表歉意。希望您可以很容易地在 Objective-C.
中编写等效项原文:
下面概述了如何在非默认位置创建一个 NSPersistentContainer
到持久存储的接口。
NSPersistentContainer
公开了 defaultDirectoryURL
,并指出:
This method returns a platform-dependent
NSURL
at which the persistent store(s) will be located or are currently located. This method can be overridden in a subclass ofNSPersistentContainer
.
如果您继承 NSPersistentContainer
并使用 containerURLForSecurityApplicationGroupIdentifier
将 defaultDirectoryURL
定义为 App Group 目录,那么您应该能够访问您的应用程序和扩展之间的容器(假设它们具有相同的应用程序组权利)。
NSPersistentContainer
还公开了 persistentStoreDescriptions
,它还具有一个 URL 实例。同样,您可以在调用 loadPersistentStoresWithCompletionHandler:
.
请注意,我没有使用过 NSPersistentContainer
,不知道这种共享是否会导致任何并发问题。
我最终完成了以下操作。 sqlite文件其实就是我的init的名字加上最后的.sqlite
+ (NSPersistentContainer*) GetPersistentContainer {
//Init the store.
NSPersistentContainer *_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"Test_App"];
//Define the store url that is located in the shared group.
NSURL* storeURL = [[[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.Test_App"] URLByAppendingPathComponent:@"Test_App.sqlite"];
//Determine if we already have a store saved in the default app location.
BOOL hasDefaultAppLocation = [[NSFileManager defaultManager] fileExistsAtPath: _persistentContainer.persistentStoreDescriptions[0].URL.path];
//Check if the store needs migration.
BOOL storeNeedsMigration = hasDefaultAppLocation && ![_persistentContainer.persistentStoreDescriptions[0].URL.absoluteString isEqualToString:storeURL.absoluteString];
//Check if the store in the default location does not exist.
if (!hasDefaultAppLocation) {
//Create a description to use for the app group store.
NSPersistentStoreDescription *description = [[NSPersistentStoreDescription alloc] init];
//set the automatic properties for the store.
description.shouldMigrateStoreAutomatically = true;
description.shouldInferMappingModelAutomatically = true;
//Set the url for the store.
description.URL = storeURL;
//Replace the coordinator store description with this description.
_persistentContainer.persistentStoreDescriptions = [NSArray arrayWithObjects:description, nil];
}
//Load the store.
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
//Check that we do not have an error.
if (error == nil) {
//Check if we need to migrate the store.
if (storeNeedsMigration) {
//Create errors to track migration and deleting errors.
NSError *migrateError;
NSError *deleteError;
//Store the old location URL.
NSURL *oldStoreURL = storeDescription.URL;
//Get the store we want to migrate.
NSPersistentStore *store = [_persistentContainer.persistentStoreCoordinator persistentStoreForURL: oldStoreURL];
//Set the store options.
NSDictionary *storeOptions = @{ NSSQLitePragmasOption : @{ @"journal_mode" : @"WAL" } };
//Migrate the store.
NSPersistentStore *newStore = [_persistentContainer.persistentStoreCoordinator migratePersistentStore: store toURL:storeURL options:storeOptions withType:NSSQLiteStoreType error:&migrateError];
//Check that the store was migrated.
if (newStore && !migrateError) {
//Remove the old SQLLite database.
[[[NSFileCoordinator alloc] init] coordinateWritingItemAtURL: oldStoreURL options: NSFileCoordinatorWritingForDeleting error: &deleteError byAccessor: ^(NSURL *urlForModifying) {
//Create a remove error.
NSError *removeError;
//Delete the file.
[[NSFileManager defaultManager] removeItemAtURL: urlForModifying error: &removeError];
//If there was an error. Output it.
if (removeError) {
NSLog(@"%@", [removeError localizedDescription]);
}
}
];
//If there was an error. Output it.
if (deleteError) {
NSLog(@"%@", [deleteError localizedDescription]);
}
}
}
} else {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
//Return the container.
return _persistentContainer;
}
solidsnake4444's
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApp")
let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.my.app")!.appendingPathComponent("MyApp.sqlite")
var defaultURL: URL?
if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
defaultURL = FileManager.default.fileExists(atPath: url.path) ? url : nil
}
if defaultURL == nil {
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
}
container.loadPersistentStores(completionHandler: { [unowned container] (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
if let url = defaultURL, url.absoluteString != storeURL.absoluteString {
let coordinator = container.persistentStoreCoordinator
if let oldStore = coordinator.persistentStore(for: url) {
do {
try coordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
} catch {
print(error.localizedDescription)
}
// delete old store
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: { url in
do {
try FileManager.default.removeItem(at: url)
} catch {
print(error.localizedDescription)
}
})
}
}
})
return container
}()
移动 NSPersistentCloudKitContainer
时,这对我有用。需要注意的几件事:
- 您需要确保
cloudKitContainerOptions
在持久存储描述中设置,否则同步将停止工作 - 不要调用
migratePersistentStore
否则你会得到重复的记录,而是使用replacePersistentStore
- 请参阅此 thread 了解更多信息 - 您可能希望在成功迁移后删除旧数据库,
destroyPersistentStore
听起来很有希望,但似乎并没有真正删除文件 - 请参阅此 question
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init(inMemory: Bool = false) {
container = NSPersistentCloudKitContainer(name: "MyCuteDB")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
} else {
// Use App Groups so app and extensions can access database
let sharedStoreURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.yourdomain.yourapp")!.appendingPathComponent("\(container.name).sqlite")
let defaultStoreURL = container.persistentStoreDescriptions.first!.url! //the URL always starts out in the default location
// move database to shared location if needed
if FileManager.default.fileExists(atPath: defaultStoreURL.path) && !FileManager.default.fileExists(atPath: sharedStoreURL.path) {
let coordinator = container.persistentStoreCoordinator
do {
try coordinator.replacePersistentStore(at: sharedStoreURL, destinationOptions: nil, withPersistentStoreFrom: defaultStoreURL, sourceOptions: nil, ofType: NSSQLiteStoreType)
try? coordinator.destroyPersistentStore(at: defaultStoreURL, ofType: NSSQLiteStoreType, options: nil)
// destroyPersistentStore says it deletes the old store but seems to be a lie so we'll manually delete the files
NSFileCoordinator(filePresenter: nil).coordinate(writingItemAt: defaultStoreURL.deletingLastPathComponent(), options: .forDeleting, error: nil, byAccessor: { url in
try? FileManager.default.removeItem(at: defaultStoreURL)
try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("\(container.name).sqlite-shm"))
try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("\(container.name).sqlite-wal"))
try? FileManager.default.removeItem(at: defaultStoreURL.deletingLastPathComponent().appendingPathComponent("ckAssetFiles"))
})
} catch {
//TODO: Handle error
}
}
// change URL from default to shared location
if FileManager.default.fileExists(atPath: sharedStoreURL.path) {
container.persistentStoreDescriptions.first!.url = sharedStoreURL
}
}
let description = container.persistentStoreDescriptions.first!
description.cloudKitContainerOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.yourdomain.yourapp")
container.loadPersistentStores { description, error in
//TODO: Handle error
}
container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
container.viewContext.automaticallyMergesChangesFromParent = true
}
}