Сохранить объекты CoreData в NSUserDefaults
Представьте себе объект CoreData (например, с именем searchEngine
).
NSManagedObjectContext
управляет некоторыми "экземплярами" этого объекта.
Конечный пользователь сможет выбрать свой "standard searchEngine"
с помощью NSPopupButton
.
selected object
NSPopupButton должен быть привязан к NSUserDefaults.
Проблема:
1)
@try {save}
a)
Если вы попытаетесь сохранить выбранный "экземпляр" непосредственно в NSUserDefaults, произойдет следующее:
- [NSUserDefaults setObject: forKey:]: попытка вставить значение не-свойства '(entity: searchEngine; id: 0x156f60; данные: { url = " http://google.de/"; someAttribute = 1; name = "google";
}) 'класса' searchEngine '.
b)
Если вы попытаетесь преобразовать "экземпляр" в NSData, это будет выглядеть следующим образом:
-[searchEngine encodeWithCoder:]: unrecognized selector sent to instance 0x1a25b0
Итак, любая идея, как получить эти объекты в данных, совместимых с plist?
2)
@try {registerDefaults}
Обычно метод registerDefaults:
реализуется в + (void)initialize
. Проблема здесь в том, что этот метод вызывается до того, как CoreData загрузит сохраненные объекты из своей базы данных. Таким образом, я не могу установить значение по умолчанию для не существующего объекта, не так ли?
Я знаю, длинные вопросы... но: try {[me обеспечить: подробности]}; D
Ответы
Ответ 1
Вам не захочется пытаться архивировать основной объект данных и хранить его. Вместо этого вы должны сохранить ключ или какой-либо другой известный атрибут и использовать его для извлечения объекта при запуске приложения.
Пример кода примера (слегка измененный из примера, опубликованного в Руководство по программированию основных данных):
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...
}
Таким образом вы сохраняете имя в пользовательских значениях по умолчанию и при необходимости извлекаете объект.
Ответ 2
Если вам нужно сохранить ссылку на определенный управляемый объект, используйте представление URI идентификатора управляемого объекта:
NSURL *moIDURL = [[myManagedObject objectID] URIRepresentation];
Затем вы можете сохранить URL-адрес пользователя по умолчанию.
Чтобы получить управляемый объект, вы используете:
NSManagedObjectID *moID = [myPersistentStoreCoordinator managedObjectIDForURIRepresentation:moIDURL];
NSManagedObject *myManagedObject = [myContext objectWithID:moID];
Единственное предостережение заключается в том, что вы должны убедиться, что исходный идентификатор управляемого объекта является постоянным - это не проблема, если вы уже сохранили объект, иначе вы можете использовать obtainPermanentIDsForObjects:error:
.
Ответ 3
Здесь самый чистый и самый короткий способ сделать это с помощью методов setURL и getURL, добавленных в 4.0, чтобы избежать дополнительных вызовов NSKeyedUnarchiver и NSKeyedArchiver:
сеттер:
+ (void)storeSomeObjectId:(NSManagedObjectID *)objectId
{
[[NSUserDefaults standardUserDefaults] setURL:[objectId URIRepresentation]
forKey:@"someObjectIdKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Getter:
+ (SomeManagedObject *)getObjectByStoredId
{
NSURL *uri = [[NSUserDefaults standardUserDefaults] URLForKey:@"someObjectIdKey"];
NSManagedObjectID *objectId = [self.persistentStoreCoordinator managedObjectIDForURIRepresentation:uri];
SomeManagedObject *object = [self.managedObjectContext objectWithID:objectId];
}