Как сохранить PersistentStore

У меня следующая проблема:

У меня есть приложение с UITableView в качестве корневого представления. В этом tableView есть разные записи, и для каждой записи (которая может быть создана пользователем) я также добавляю постоянное хранилище в свое приложение.

Таким образом, когда я запускаю приложение с нуля (без сохраненных данных и т. д.) и добавляю запись, также создается хранилище persistenceStore, и когда я нажимаю на tableViewCell, я могу сохранить данные в этом сгенерированном хранилище persistenceStore. Это отлично работает, если я создаю запись, а также просматриваю запись во время одного запуска.

НО

Если я закрою приложение и запущу снова, щелкнув ту же запись, я получу следующее сообщение об ошибке:

NSFetchRequest *allUsers = [[NSFetchRequest alloc] init];
[allUsers setAffectedStores:[NSArray arrayWithObject:[[self.tableViewContext persistentStoreCoordinator] persistentStoreForURL:storeURL]]];

* Завершение работы приложения из-за необработанного исключения "NSInvalidArgumentException", причина: "* -[NSArray initWithObjects:count:]: попытка вставить нулевой объект в объекты [0]"

Итак, кажется, что я хочу добавить магазин, который на самом деле равен нулю, потому что (я так думаю) система не может найти ни одного магазина по этому заданному storeURL (который совпадает с тем, где я создал магазин при первом запуске) .

Итак, я предполагаю, что во втором прогоне persistenceStore нет, поэтому он не сохраняется должным образом в первом прогоне, где он был создан.

Итак, как я могу сохранить персистентное хранилище после его добавления в персистентсторекоординатор?

Обновление:

Кажется, я определил основную проблему. ПостоянныйStoreCoordinator изменился после первого запуска. Итак, как мне сохранить все эти вещи (managedObjectContext, persistenceStoreCoordinator) перед закрытием приложения?

Кто-нибудь может мне помочь?

Обновление 2

Вот как я создаю магазин:

    NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentPath = [searchPaths objectAtIndex:0];
    NSString* storeFileName = [NSString stringWithFormat:@"%@",newItem.name];
    NSURL *storeURL = [NSURL fileURLWithPath:[documentPath stringByAppendingPathComponent:storeFileName]];                            
     NSError* saveToStoreError;
    if(![[self.addContext persistentStoreCoordinator] addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&saveToStoreError]){
     NSLog(@"Error: %@, %@", saveToStoreError, [saveToStoreError userInfo]);
     abort();
    }
    else
    {
      NSError *saveStoreError;
      if(![self.addContext save:&saveStoreError])
      {
           NSLog(@"Saving Data wasn't possible!");
      }
    }

Обновление 3 Итак, после продолжительного тестирования вот мои результаты:

  • Создание магазинов работает нормально. Я могу создать несколько хранилищ, а также получить к ним доступ и заполнить их, если я нахожусь в одном запуске своего приложения.

Так что что-то меняется с перезапуском моего приложения. Я думаю, что ошибка должна быть связана с ManagedObjectContext, PermanentStoreCoordinator или СОХРАНЕНИЕМ хранилищ.

Должен ли я изменить какие-либо параметры в моем делегате приложения для настройки manageObjectContext или persistenceStoreCoordinator?

Спасибо!


person andi1984    schedule 06.09.2011    source источник
comment
Я думаю, вы догадались о непосредственной причине вашей проблемы: нет файла для URL-адреса постоянного хранилища, который вы запрашиваете. Почему нет файла, это больше связано с вашим кодом, который создает постоянное хранилище. Вы должны добавить это к вопросу.   -  person morningstar    schedule 07.09.2011
comment
Я думаю, что СОЗДАНИЕ не проблема, потому что все отлично работает при первом запуске, поэтому магазин должен быть там по заданному URL. Но, похоже, во втором прогоне его нет, поэтому я думаю, что не сохранил его должным образом. Но создание должно быть в порядке, на мой взгляд.   -  person andi1984    schedule 07.09.2011
comment
Я думаю, вы можете неправильно понять что-то важное о том, как следует использовать Core Data. Очень редко создается новое постоянное хранилище для каждой записи в таблице. Магазин предназначен для хранения целых графов объектов, а не их фрагментов.   -  person TechZen    schedule 08.09.2011
comment
Нет, так это следующим образом: В моем магазине хранится много разных сущностей. Итак, допустим, вы хотите сделать приложение для разных кинотеатров, их программы, контактной информации и т. д. Разве вы не будете хранить эту информацию для каждого кинотеатра в одном магазине? Вот как я его использую. В каждом магазине есть несколько объектов, которые я использую после того, как пользователь нажимает на запись в UITableView.   -  person andi1984    schedule 08.09.2011


Ответы (5)


То, как вы озвучиваете свою проблему, заставляет меня подозревать некую путаницу.

что persistenceStore меняется после каждого перезапуска. Это обычный случай?

Да, это! NSPersistentStore является объектом Objective-C, как и любой другой объект. Таким образом, он не сохраняется при запуске. Вам нужно воссоздавать его каждый раз.

Что является постоянным в NSPersistentStore, так это файл, на который он указывает. Но каждый раз, когда вы запускаете свое приложение, вы должны воссоздавать новый объект NSPersistentStore, возможно, указывая на тот же файл (определяемый аргументом url для initWithPersistentStoreCoordinator:configurationName:URL:options:).

Так как же установить переменную storeURL?

person Jean-Denis Muys    schedule 07.09.2011
comment
Хм, я этого не понимаю. Итак, у меня есть NSPersistentStore, который я создал, а затем я получаю доступ к этому хранилищу в ТОМ ЖЕ запуске, и все работает идеально. Таким образом, он может получить доступ к этому магазину. Или вы имеете в виду NSPersistentStoreCoordinator? Итак, я создал магазин и сохранил его. Поэтому я думаю, что мне нужно перенастроить свой NSPersistentStoreCoordinator после перезапуска. Это та же тема, о которой вы говорили выше? Что меня смущает, так это то, что [__persistentStoreCoordinator persistenceStores] имеет более высокое значение перед закрытием приложения, чем после перезапуска приложения. - person andi1984; 07.09.2011

Чтобы сохранить контекст управляемого объекта, используйте метод «save:» NSManagedObjectContext после добавления нового постоянного хранилища и перед закрытием приложения. Затем, чтобы проверить правильность добавления постоянных хранилищ, используйте метод «persistentStores» NSPersistentStoreCoordinator, чтобы определить доступные допустимые хранилища.

person filjedi    schedule 07.09.2011
comment
Спасибо за это. Вот результаты: После вызова addPersistentStoreWithType... есть 2 хранилища (основное хранилище делегата приложения и это вновь добавленное один раз), поэтому на одно хранилище больше, чем до вызова этого метода. Поэтому я думаю, что магазин спасен. Но, после закрытия приложения и перезапуска, снова есть только один магазин (основной магазин). Поэтому я думаю, что это как-то связано с тем, что persistenceStoreCoordinator и manageObjectContext меняются при перезапуске. Есть ли способ их заморозить? - person andi1984; 07.09.2011

Интересно, проблема не в вызовах Core Data, а в том, когда они вызываются?

Когда вы «закрываете приложение и запускаете снова» ... приложение завершается между ними или оно работает в фоновом режиме? IIRC, который тонко повлияет на то, что вызывается в вашем делегате приложения. В зависимости от того, как там устроены WRT Core Data, возможно, что-то случайно вызывается (или пропускается).

Мне было бы интересно посмотреть, что произойдет, если вы проследите каждый отдельный метод, связанный с Core Data, в вашем делегате приложения (или где бы они ни находились), чтобы увидеть, сможете ли вы поймать его с поличным. (Если где-то опубликован минимальный тестовый пример, поделитесь, пожалуйста!)

person Joe D'Andrea    schedule 07.09.2011
comment
Привет, я думаю, мне следует изменить слово ПЕРЕЗАПУСК на ОСТАНОВИТЬ ПРИЛОЖЕНИЕ И НАЧАТЬ СНОВА. Поэтому я тестирую его на симуляторе iOS, выхожу из него и снова перезапускаю, а затем возникает такое поведение. Итак, для меня (как для новичка) это выглядит так: если я создаю новую запись, текущий NSPersistentStoreCoordinator моего делегата приложения знает об этом, и когда я останавливаю симулятор и снова перезапускаю его, появляется новый storeCoordinator, у которого нет Информация об этих магазинах. Так что это мое ощущение, что там что-то не так, но это может быть и полная ерунда. :-/ - person andi1984; 07.09.2011

Это было просто легко.

Я не установил addPersistentStoreWithType после перезагрузки в представлении, где я пытался получить данные из этого хранилища.

Извините за этот пост. Просто легко ;-) ударя головой о стену

person andi1984    schedule 07.09.2011
comment
Это хорошо! Вы задокументировали все шаги и нашли решение. Теперь другие выиграют. Коллаборативные системы — это круто. :) - person Joe D'Andrea; 07.09.2011
comment
Верно. Я люблю stackoverflow и всех вас, кто помогает мне найти мои более или менее серьезные проблемы ;-) - person andi1984; 08.09.2011

Взгляните на Window-приложение в шаблонах Xcode.

Это создает для вас целый стек Core-Data — постоянное хранилище, координатор постоянного хранилища и контекст управляемого объекта.

Предполагая, что ваше приложение не требует этого, у вас должно быть только одно постоянное хранилище. По сути, это файл, в который записываются данные. Глядя на ваш код, кажется, что вы пытаетесь создать свой собственный магазин каждый раз, когда сохраняете данные.

Вы должны скопировать основные методы стека данных из шаблона, который я предложил выше. Вам не нужно самостоятельно обращаться к постоянному хранилищу или координатору постоянного хранилища. Все, что вам нужно, — это контекст управляемого объекта, созданный делегатом приложения.

person Ashley Mills    schedule 06.09.2011
comment
Я уже использую оконное приложение. Но это не решает проблему. Я думаю, что основная проблема в том, что persistenceStore меняется после каждого перезапуска. Это обычный случай? - person andi1984; 07.09.2011