Сохранить объекты CoreData в NSUserDefaults
-
20-08-2019 - |
Вопрос
Представьте себе объект CoreData (напримерназванный searchEngine
).
NSManagedObjectContext
управляет некоторыми "экземплярами" этой сущности.
Конечный пользователь сможет выбрать свой "standard searchEngine"
с помощью NSPopupButton
.
В selected object
of NSPopUpButton должен быть привязан к NSUserDefaults .
Проблема:
1)
@попробовать{сохранить}
a)
Если вы попытаетесь сохранить выбранный "экземпляр" непосредственно в NSUserDefaults, произойдет что-то вроде этого:-[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value ' (entity: searchEngine; id: 0x156f60 ; data: { url = "http://google.de/"; someAttribute = 1; name = "google"; })' of class 'searchEngine'.
b)
Если вы попытаетесь преобразовать "экземпляр" в NSData, получится следующее:-[searchEngine encodeWithCoder:]: unrecognized selector sent to instance 0x1a25b0Итак, есть какие-нибудь идеи, как получить эти объекты в plist-совместимых данных?
2)
@try{Ошибки при регистрации}Обычно в
registerDefaults:
метод реализован в+ (void)initialize
.Проблема здесь в том, что этот метод вызывается до того, как CoreData загрузит сохраненные объекты из своей базы данных.Таким образом, я не могу установить значение по умолчанию для несуществующего объекта, верно?
Я знаю, длинные вопросы...но:попробуйте{[я предоставлю: подробности]};D
Решение
Вы бы не хотели пытаться заархивировать объект core data и сохранить его.Вместо этого вы могли бы сохранить ключ или какой-либо другой известный атрибут и использовать его для извлечения объекта при запуске приложения.
Некоторый пример кода (слегка измененный по сравнению с примером, опубликованным в Руководство по программированию основных данных):
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:@"SearchEngine" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"engineName LIKE[c] '%@'", selectedEngineName];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil)
{
// Deal with error...
}
Таким образом, вы сохраняете имя в пользовательских значениях по умолчанию и при необходимости извлекаете объект.
Другие советы
Если вам нужно сохранить ссылку на определенный управляемый объект, используйте представление URI его идентификатора управляемого объекта:
NSURL *moIDURL = [[myManagedObject objectID] URIRepresentation];
Затем вы можете сохранить URL-адрес по умолчанию для пользователя.
Чтобы извлечь управляемый объект, вы используете:
NSManagedObjectID *moID = [myPersistentStoreCoordinator managedObjectIDForURIRepresentation:moIDURL];
NSManagedObject *myManagedObject = [myContext objectWithID:moID];
Единственное предостережение заключается в том, что вы должны убедиться, что исходный идентификатор управляемого объекта является постоянным - это не проблема, если вы уже сохранили объект, в качестве альтернативы вы можете использовать obtainPermanentIDsForObjects:error:
.
Вот самый чистый и короткий способ на данный момент сделать это с использованием методов setUrl и getURL, добавленных в 4.0, чтобы избежать дополнительных вызовов NSKeyedUnarchiver и NSKeyedArchiver:
Сеттер:
+ (void)storeSomeObjectId:(NSManagedObjectID *)objectId
{
[[NSUserDefaults standardUserDefaults] setURL:[objectId URIRepresentation]
forKey:@"someObjectIdKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Добытчик:
+ (SomeManagedObject *)getObjectByStoredId
{
NSURL *uri = [[NSUserDefaults standardUserDefaults] URLForKey:@"someObjectIdKey"];
NSManagedObjectID *objectId = [self.persistentStoreCoordinator managedObjectIDForURIRepresentation:uri];
SomeManagedObject *object = [self.managedObjectContext objectWithID:objectId];
}