Подтвердить что ты не робот

Доступ к базовым базам данных SQL в iOS 8 Extension (совместное использование данных между расширением приложения и виджета)

Проблема:

Невозможно получить доступ к базе данных основных данных приложения из расширения Widget в представлении Today.

Само приложение может читать и записывать в базу данных в соответствии с нормами в iOS 8, но расширение не сможет создать хранилище, что даст ошибку, неспособность записать файл.

Журнал выглядит следующим образом:

Error Domain=NSCocoaErrorDomain Code=512 "The operation couldn’t be completed. (Cocoa error 512.)"

reason = "Failed to create file; code = 2
4b9b3361

Ответ 1

Виджеты не могут получить доступ к каталогу NSDocuments, который обычно хранит их базу данных.

Решение состоит в том, чтобы сначала создать группу приложений

Перейдите по ссылке: Project - Target - Группы приложений - Добавить новый контейнер

Назовите контейнер, т.е. 'group.mycontainer'

Повторите процесс для Widget Target, используя одно и то же имя для контейнера.

Затем запишите свою базу данных в контейнер группы.

Итак:

NSURL *storeURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory  inDomains:NSAllDomainsMask] lastObject];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

становится:

NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.mycontainer"];
storeURL = [storeURL URLByAppendingPathComponent:@"db.sqlite"];

И инициализация магазина должна быть такой:

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]

Ответ 2

Просто выяснилось, что файлы группы приложений не получают резервное копирование с использованием стандартной процедуры резервного копирования iOS.

Имейте в виду, что пользователь может потерять все свои данные приложения после восстановления iOS, если сохранить постоянное хранилище в контейнере группы приложений.

UPDATE

rdar://18750178

UPDATE

кажется исправленным в iOS 8.1, Apple ребята обменялись сообщениями и попросили проверить проблему в iOS 8.1 независимо от того, исправлено это или нет (нагло ли это нет?). Я не проверял его, поэтому имейте в виду. Во всяком случае, хранение хранилища в AppGroups является мертвой идеей, если вы поддерживаете дефектный iOS 8.0

Ответ 3

Измените

[MagicalRecord setupCoreDataStackWithStoreNamed:@"Database"];

к

 - (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];
}

Ответ 4

То же самое для 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)
}

Не забудьте установить этот метод для обоих: AppDelegate и Сегодня расширение