Доступ к базовым базам данных 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
Ответы
Ответ 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 и Сегодня расширение