当我使用核心数据模板创建在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();
}
我想补充一点,访问历史中的核心数据的今天和的iMessage扩展。从我读,我需要的,如果它存在于一个共享的应用程序容器迁移这些数据。我会怎么做呢?
该代码是在目标C.
我已阅读这涉及其他问题,但他们都似乎是在苹果改变了核心数据的工作,使其更容易的方式。正如你可以在我的代码中看到的,我从来没有指定的数据存储准确的文件名是什么。我看到每个实例有这样的事情“My_History.sqllite”。我甚至不知道我的是一个精简版的SQL数据库,可以仅仅通过代码创建的。
我最终得到它执行以下操作。 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;
}
更新:
要迁移现有的持久性存储,该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
}
请注意,上面没有经过测试,所以它是不完整的我还没有办理选配。另外,我为它在斯威夫特是道歉。希望这是很容易的给你写在Objective-C的等价物。
原版的:
下面简单介绍一下如何创建一个NSPersistentContainer
接口持久存储在一个非默认位置。
该NSPersistentContainer
公开defaultDirectoryURL
,并指出:
该方法返回一个依赖于平台的
NSURL
在该持久存储(一个或多个)将位于或当前位于。这种方法可以在NSPersistentContainer
的子类所覆盖。
如果你继承qazxswpoi并定义NSPersistentContainer
是使用defaultDirectoryURL
的应用程序组的目录,你应该然后能够将应用程序和扩展之间访问容器(假设它们具有相同的应用程序组的权利)。
containerURLForSecurityApplicationGroupIdentifier
也暴露出NSPersistentContainer
还设有一个URL实例。同样,你可以调用persistentStoreDescriptions
之前更新该到App集团URL。
请注意,我没有使用loadPersistentStoresWithCompletionHandler:
,而且不知道这种共享是否会导致出现并发问题。
NSPersistentContainer
的solidsnake4444节省了我的一天。这里是雨燕5.0的版本。
answer