[英]Accessing Core Data SQL Database in iOS 8 Extension (Sharing Data Between App and Widget Extension)
Problem: 问题:
Unable to access application's Core Data database from within a Widget Extension in the Today View. 无法从“今日”视图中的窗口小部件扩展中访问应用程序的核心数据数据库。
The app itself is able to read and write to the database as per normal under iOS 8, but the extension will fail to create the store, giving the error, unable to write to file. 该应用程序本身可以在iOS 8下正常读取和写入数据库,但是扩展名将无法创建存储,从而产生错误,无法写入文件。
The log is the following: 日志如下:
Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)"
reason = "Failed to create file; code = 2
Widgets are unable to access the NSDocuments directory, which is where one would normally store their database. 小部件无法访问NSDocuments目录,该目录通常是存储它们的数据库的位置。
The solution is to first create an App Group 解决方案是先创建一个应用程序组
Go to: Project - Target - App Groups - Add New Container 转到:项目-目标-应用组-添加新容器
Name the container, ie 'group.mycontainer' 命名容器,即“ group.mycontainer”
Repeat the process for the Widget's Target using the same name for the container. 对容器使用相同的名称,对Widget的Target重复此过程。
Then write your database to your group container. 然后将数据库写入组容器。
So: 所以:
NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSAllDomainsMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
Becomes: 成为:
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
And initialising the store should be like so: 初始化商店应该是这样的:
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];
NSPersistentStore *store = nil;
store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:nil
error:&error]
Just figured out that the app group files do not get backed up using the standard iOS backup procedure. 刚刚发现应用程序组文件不会使用标准的iOS备份过程进行备份。
Keep in mind that the user may lose all their app data after restoring iOS if you keep the persistent store in an app group container. 请记住,如果将持久性存储存储在应用程序组容器中,则用户在还原iOS后可能会丢失所有应用程序数据。
UPDATE 更新
rdar://18750178 rdar:// 18750178
UPDATE 更新
seems like fixed in iOS 8.1, Apple guys messaged me and asked to check the problem in iOS 8.1 whether it fixed or not (quite impudent isn't?). 苹果人似乎给我发消息,问我是否要解决iOS 8.1中的问题,并要求检查iOS 8.1中的问题是否已解决(不是很无礼吗?)。 I haven't tested it, so keep in mind. 我还没有测试过,所以请记住。 Anyway, keeping storage in AppGroups is a dead idea in case you are supporting defective iOS 8.0 无论如何,如果您要支持有缺陷的iOS 8.0,则在AppGroups中保留存储是一个绝妙的主意
Change 更改
[MagicalRecord setupCoreDataStackWithStoreNamed:@"Database"];
to 至
- (void)setupCoreDataStack
{
if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil)
{
return;
}
NSManagedObjectModel *model = [NSManagedObjectModel MR_defaultManagedObjectModel];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.yourgroup"];
storeURL = [storeURL URLByAppendingPathComponent:@"Database.sqlite"];
[psc MR_addSqliteStoreNamed:storeURL withOptions:nil];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:psc];
[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:psc];
}
The same for Swift: 对于Swift同样如此:
private func setupCoreDataStack() {
if NSPersistentStoreCoordinator.MR_defaultStoreCoordinator() != nil {
return
}
let managedObjectModel = NSManagedObjectModel.MR_defaultManagedObjectModel()
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
var storePath = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(PBOSharedSuiteGroupName)
storePath = storePath!.URLByAppendingPathComponent("AppName.sqlite")
var error: NSError?
persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storePath, options: nil, error: &error)
NSPersistentStoreCoordinator.MR_setDefaultStoreCoordinator(persistentStoreCoordinator)
NSManagedObjectContext.MR_initializeDefaultContextWithCoordinator(persistentStoreCoordinator)
}
Remember to attach this method to both: AppDelegate and Today Extension 切记将此方法同时应用于: AppDelegate和Today Extension
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.