简体   繁体   English

在iOS 8扩展程序中访问核心数据SQL数据库(在App和Widget扩展程序之间共享数据)

[英]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 切记将此方法同时应用于: AppDelegateToday Extension

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在iOS8中在App和Extension之间共享核心数据堆栈和数据 - Sharing a Core Data stack and data between App and Extension in iOS8 在iOS App和Todays Extension之间共享数据 - Sharing Data Between iOS App and Todays Extension 在 iOS 8 共享扩展和主应用程序之间共享数据 - Sharing data between an iOS 8 share extension and main app 在App Extension和Conainer App之间共享数据 - Sharing data between app extension and conainer app 在Swift中的应用和今日扩展之间共享核心数据数据库 - Share Core Data database between app and today extension in Swift iOS Today Extension - 在之间共享核心数据 - iOS Today Extension - Share core data between iOS Today扩展NSUserDefaults使用回调与包含应用程序共享数据 - iOS Today Extension NSUserDefaults Sharing Data with Containing App using Callbacks 在通知服务扩展和主应用之间共享数据 - Sharing data between an notification service extension and main app iOS 8小部件,向前和向后在应用程序组之间共享数据 - iOS 8 widget, sharing data between app groups forward and backward 从容器应用程序和扩展程序访问核心数据 - Accessing Core Data from both container app and extension
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM