MagicalRecord: несколько баз данных
У меня есть приложение, которое использует MagicalRecord, и я предварительно заполняю базу данных большим количеством данных, которые используются для справки. В пределах той же модели данных у меня есть определяемая пользователем информация, относящаяся к вещам, которые пользователь может делать в приложении.
Приложение было отклонено, поскольку предварительно заполненные данные должны быть помечены как "не делать резервные копии". Таким образом, я хотел бы иметь эти данные в отдельном хранилище данных, чтобы сохранить данные пользователя как резервные.
Есть ли способ иметь два отдельных хранилища данных с помощью MagicalRecord?
Ответы
Ответ 1
Я думаю, что это возможно, но не слишком легко.
Как вы знаете, для работы с несколькими базами данных вы должны внести некоторые изменения в свой PersistentStoreCoordinator
, поэтому у него будет два PersistentStores
. После этого вы создадите стек Core Data следующим образом:
![enter image description here]()
Другим способом является создание двух отдельных PersistentStoreCoordinators, каждый из которых имеет один магазин.
В Magical Record существует несколько методов класса для добавления хранилищ в
NSPersistentStoreCoordinator + MagicalRecord.h.
- (NSPersistentStore *) MR_addInMemoryStore;
- (NSPersistentStore *) MR_addAutoMigratingSqliteStoreNamed: (NSString *) storeFileName;
- (NSPersistentStore *) MR_addSqliteStoreNamed: (id) storeFileName withOptions: (__ autoreleasing NSDictionary *) options;
Я думаю, что это то место, где вы могли бы сделать то, что хотите.
Также я должен упомянуть, что весь процесс настройки стека идет в MagicalRecord + Setup.h
+ (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName
Итак, вы можете добавить свои магазины и координаторы.
Я никогда не справлялся с этим сам, это было просто краткое исследование возможного решения.
Ответ 2
Мне удалось решить эту проблему, используя конфигурации. Поскольку Magical Record всегда отправляет null
для параметра конфигурации, я разломал setupCoreDataStackWithAutoMigratingSqliteStoreNamed
и заменил его на метод, поддерживающий несколько конфигураций.
Поскольку Magical Record отлично справляется с обработкой автоматических миграций, я сначала вызываю setupCoreDataStackWithAutoMigratingSqliteStoreNamed
, затем очистка, а затем я предоставляю свой код замены.
У меня есть одна объектная модель с моими объектами семенных данных, которым назначена конфигурация "Семя" и пользовательские объекты, назначенные для конфигурации "Пользователь". Магическая запись уже была инициализирована, поэтому при необходимости может автоматически мигрировать.
+(void) RB_setupMultipleStores:(NSString *) seedStoreName userStore:(NSString *) userStoreName
/* change persistent store to one with multiple configurations. Assumes Magical Record is initialized. */
{
NSError * error= nil;
[MagicalRecord cleanUp];
NSManagedObjectModel * model = [NSManagedObjectModel MR_defaultManagedObjectModel];
NSURL *seedURL = [NSPersistentStore MR_urlForStoreName:[seedStoreName stringByAppendingString:@".sqlite"]];
NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
NSPersistentStore * seedStore =[coordinator
addPersistentStoreWithType:NSSQLiteStoreType
configuration:@"Seed"
URL:seedURL
options:options
error:&error];
if (!seedStore || error)
{
NSLog(@"Error setting up seed store:%@ for %@", [error localizedDescription], seedURL);
exit(-1);
}
NSURL *userURL = [NSPersistentStore MR_urlForStoreName:[userStoreName stringByAppendingString:@".sqlite"]];
NSPersistentStore * userStore = [coordinator
addPersistentStoreWithType:NSSQLiteStoreType
configuration:@"User"
URL:userURL
options:options
error:&error];
if (!userStore || error)
{
NSLog(@"Error setting up user store:%@ for %@", [error localizedDescription], userURL);
exit (-1);
}
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator];
[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator];
}
Кроме того, MR 3.0 имеет одновременные стеки, которые могут решить проблему после ее завершения.
Ответ 3
Сохранение данных для разных объектов Core Data в разных файлах хранилища хорошо поддерживается и довольно просто. Тем не менее, MagicalRecrd не предоставляет никаких удобных методов для настройки вашего пакета Core Data таким образом. Вам просто нужно выделить свой стек вручную и сообщить MagicalRecord, чтобы использовать созданный NSPersistentStoreCoordinator
. Вот как я сделал это быстро:
import Foundation
import CoreData
import MagicalRecord
class CoreDataSetup {
static func setupAutoMigratingStack(withContentConfigurationName contentConfigurationName: String, userConfirgurationNameName: String) {
MagicalRecord.cleanUp()
let managedObjectModel = NSManagedObjectModel.MR_defaultManagedObjectModel()
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!)
let contentURL = NSPersistentStore.MR_urlForStoreName(contentConfigurationName + ".sqlite")
let userURL = NSPersistentStore.MR_urlForStoreName(userConfirgurationNameName + ".sqlite")
let options = [
NSMigratePersistentStoresAutomaticallyOption : true,
NSInferMappingModelAutomaticallyOption: true,
NSSQLitePragmasOption: ["journal_mode": "DELETE"]
]
do {
try persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: contentConfigurationName, URL: contentURL, options: options)
try persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: userConfirgurationNameName, URL: userURL, options: options)
NSPersistentStoreCoordinator.MR_setDefaultStoreCoordinator(persistentStoreCoordinator)
NSManagedObjectContext.MR_initializeDefaultContextWithCoordinator(persistentStoreCoordinator)
} catch {
print("Error adding persistent store to coordinator: \(error) ")
}
}
}
Обратите внимание, что в моем коде я имею в виду вашу концепцию "семенного" хранилища как "контент" и определяемое пользователем хранилище как "пользователь".
Чтобы выполнить второй аспект вашего вопроса, настроив хранилище содержимого, чтобы он не был скопирован, вам просто нужно поиграть с URL-адресами, в которых вы храните каждый магазин, помещая хранилище содержимого в резервный временный каталог без резервной копии, и копировать его в это место до запуска из вашего пакета приложений, если он не существует.