#cocoa #core-data
#cocoa #core-data
Вопрос:
Компакт-диск стал для меня огромным испытанием, и мне еще многое предстоит сделать, но любая помощь в следующем может помочь мне снять текущий груз со своих плеч!
Я пытаюсь написать метод, который реализует «Сохранить как ..» для пользователя в моем приложении CD.
Пока у меня есть:
[saveAsPanel beginSheetModalForWindow:window completionHandler:^(NSInteger userResult)
{
if (userResult == NSOKButton) {
NSPersistentStoreCoordinator *psc = [self persistentStoreCoordinator];
NSURL *oldURL = [self URLOfInternalStore]; //returns the current store's URL
NSURL *newURL = [saveAsPanel URL];
NSError *error = nil;
NSPersistentStore *oldStore = [psc persistentStoreForURL:oldURL];
NSPersistentStore *sqLiteStore = [psc migratePersistentStore:oldStore
toURL:newURL
options:nil
withType:NSXMLStoreType
error:amp;error];
}
}];
К сожалению, я просто получаю сообщение об ошибке:
Постоянное хранилище объекта недоступно из координатора этого NSManagedObjectContext.
Должен ли я «удалить», а затем «addPersistentStore …», чтобы обновить его до нового URL? Документы, похоже, предполагают, что все будет обработано с помощью метода ‘migrate’.
Заранее спасибо!
Редактировать:
Хорошо, хорошо, я придумал свой собственный «грязный» метод. Я могу представить, что это не одобренный способ выполнения действий, но ошибок не возникает, и приложение всегда работает должным образом (я тоже не часто могу это сказать!):
-(IBAction)saveAsAction:(id)sender
{
NSSavePanel *saveAsPanel = [NSSavePanel savePanel];
[saveAsPanel beginSheetModalForWindow:window completionHandler:^(NSInteger userResult)
{
if (userResult == NSOKButton) {
[self saveAction:@"saveAsCalling"];
NSURL *newURL = [saveAsPanel URL];
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:internalStore] toURL:newURL error:amp;error];
//internalStore is a hard-wired NSString that holds the path to the bundle's database
}
}];
}
-(IBAction)loadAction:(id)sender
{
NSOpenPanel *loadPanel = [NSOpenPanel openPanel];
[loadPanel beginSheetModalForWindow:window completionHandler:^(NSInteger userResult)
{
if (userResult == NSOKButton) {
[self saveAction:@"loadCalling"];
NSURL *newURL = [loadPanel URL];
NSURL *oldURL = [NSURL fileURLWithPath:internalStore];
NSError *error = nil;
NSPersistentStoreCoordinator *psc = [SELF_MOC persistentStoreCoordinator];
[psc removePersistentStore:[[self persistentStoreCoordinator] persistentStoreForURL:oldURL] error:amp;error];
[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:newURL options:nil error:amp;error];
[[NSFileManager defaultManager] removeItemAtURL:oldURL error:amp;error];
[[NSFileManager defaultManager] copyItemAtURL:newURL toURL:oldURL error:amp;error];
[psc removePersistentStore:[[self persistentStoreCoordinator] persistentStoreForURL:newURL] error:amp;error];
[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:oldURL options:nil error:amp;error];
}
}];
}
Основное рассуждение таково: чтобы выполнить «SaveAs …», я просто копирую файл SQLLite store в mainBundle туда, где пользователь выберет, и переименовываю его в то, что они хотят — согласно предложению TechZen.
Чтобы выполнить «загрузку», я сначала удаляю PersistentStore из файла пакета, добавляю тот, который только что выбрал пользователь. Удалите хранилище пакетов (которое теоретически сейчас не используется), а затем скопируйте выбранный пользователем вариант обратно в пакет. Наконец, выполняются две операции remove и addPersistentStore, чтобы указать приложению обратно на файл его пакета, который теперь выбирается пользователем.
Надеюсь, это имеет смысл. Если у кого-нибудь есть какие-либо мысли о том, насколько это непрофессиональная методология, то, пожалуйста — будьте добры, поскольку я довольно новичок — дайте мне знать. Я не могу найти ничего более элегантного.
Я знаю, что Apple не нравится, когда вы используете removePersistentStore и addPersistentStore, но, как я уже сказал, никаких сообщений об ошибках не поступало (в моем реальном коде я разбросал строки NSLog повсюду, чтобы сообщить, какая ошибка содержится).
Ответ №1:
Вы используете SaveAs...
только в приложении на основе документов. Если вы используете Core Data в качестве своей модели, вам необходимо использовать NSPersistentDocument для сохранения ваших данных. Он обеспечивает SaveAs...
функциональность, которую вы ищете.
Прямые основные данные используются для приложений, похожих на базы данных, в которых все приложение работает на основе одного набора данных (более или менее.)
Комментарии:
1. Спасибо TechZen. Таким образом, дальнейшим способом может быть создание базовой копии файла текущего хранилища ..? Я видел онлайн-сообщение, в котором кто-то закрыл текущее окно, скопировал файл sql, а затем снова открыл окно приложения. Они признали, что это не элегантно!
2. Да, простое копирование постоянного хранилища привело бы к тому же, что и
Save as...
3. Спасибо TechZen, я только что увидел ваш комментарий после того, как опубликовал свою правку.
4. Есть одно важное различие между «Сохранить как …» и копией постоянного хранилища. При выполнении первого Core Data выполнит проверку достоверности каждого объекта в хранилище. Если критерии проверки со временем изменились в вашем приложении, это может привести к новым ошибкам проверки для вашего пользователя.