У меня есть Базовое Применение данных, которое я планирую обновить с новой схемой. Легкая миграция, кажется, работает, но она занимает время пропорциональная на сумму данных в базе данных. Это происходит в didFinishLaunchingWithOptions
фаза приложения.
Я хочу избежать <app> failed to launch in time
проблемы, таким образом, я предполагаю, что не могу удержать миграцию didFinishLaunchingWithOptions
метод.
Я предполагаю, что лучший метод вовлек бы выполнение миграции в фоновый поток. Я предполагаю также, что должен был бы задержать загрузку основного ViewController, пока загрузка не завершается для избегания использования managedObjectContext
пока инициализация не завершается.
Это имеет смысл и является там примером кода (возможно, в демонстрационных проектах Apple) этого вида инициализации?
Вы не можете поместить миграцию в NSOperation
, потому что она должна выполняться в основном потоке. Что вам нужно сделать, так это выйти из метода -applicationDidFinishLaunching:
, не касаясь стека Core Data.Если вы можете быстро завершить этот метод (и этот цикл цикла выполнения), то ваше приложение не будет завершено, и вы можете потратить столько времени, сколько пользователь будет терпеть, чтобы завершить миграцию.
См. Мой ответ здесь: Как перейти с автоматической облегченной миграции Core Data на ручную?
Чтобы прояснить мою позицию по этому поводу. По сути, можно делать что угодно. Однако выполнение миграции в фоновом потоке - плохая идея . Чрезвычайно сложно гарантировать, что стек никогда никогда не будет затронут во время миграции, а также целый ряд других осложнений, связанных с потоками.
Это возможно , но это связано с высокой степенью риска, в котором нет необходимости. Основной поток можно и нужно использовать для миграции основного стека Core Data. Легко создать модальное диалоговое окно, чтобы пользователь знал, что происходит миграция, а затем выполнить миграцию в основном потоке.
Если вы находитесь в ситуации, когда миграция занимает значительное время, также настоятельно рекомендуется переключиться с автоматической миграции на ручную с помощью модели сопоставления, чтобы вы могли:
С момента первоначального ответа на этот вопрос многое изменилось.
Теперь ответ на миграцию - запускать ее в фоновой очереди (через dispatch_async
вызова NSPersistentStoreCoordinator
addStore ...
).
Это также означает, что вам необходимо убедиться, что ваш пользовательский интерфейс может обрабатывать уровень сохраняемости, являющийся пустым / недоступным в течение неизвестного периода времени. Как это сделать, зависит от вашего приложения.
Например, у вас может быть временный пользовательский интерфейс, который показывает танцующих кошек, в то время как уровень персистентности выполняет миграцию. Пользовательский опыт зависит от вас.
Однако вы НЕ хотите, чтобы пользователь мог создавать данные во время миграции. Это затруднит слияние позже (если вообще).
Вы можете поместить обновления основных данных в NSOperation
, который можно добавить в очередь операций в didFinishLaunching ...
и который может работать в фоновом режиме, переопределив параметр -основной
метод операции.
Взгляните на эту страницу руководства , чтобы получить общее представление о том, что здесь задействовано. Используйте KVO со свойством операции isFinished
, чтобы обновить состояние вашего приложения - вы можете использовать значение этого ключа, чтобы предупредить пользователя о том, что миграция все еще выполняется, например, перед представление любых данных.
Извини, Маркус, я вынужден с уважением не согласиться. Вы можете мигрировать в фоновом режиме.
Моя миграция выполняется в фоновом потоке. На медленных устройствах это может занять более 10 секунд, поэтому я запускаю его в фоновом потоке и использую конкретный контроллер модального представления для отображения прогресса.
Для этого нужно разделить обычную последовательность загрузки на две фазы.
Этап 1) Делайте все, что вы обычно делаете при запуске, для чего не требуются управляемые объекты. Конец этого этапа определяется проверкой, чтобы определить, требуется ли миграция.
Этап 2) Делайте все, что обычно происходит при запуске, для чего требуются управляемые объекты. Эта фаза является непосредственным продолжением фазы 1), когда миграция не требовалась.
Таким образом, ваше приложение завершит запуск независимо от продолжительности обработки миграции.
Чтобы успешно выполнить длительную миграцию, я использую контроллер модального представления, показывающий пользователю обратную связь о ходе миграции. Затем я начинаю миграцию в фоновом потоке, в то время как контроллер модального представления использует KVO для обновления индикатора выполнения.
В конце миграции он закрывает весь «стек» основных данных, а обратный вызов в основной поток отклоняет модальное окно и переходит к Фазе 2).
Весь этот процесс работает безупречно, хотя у меня все еще есть открытый вопрос о том, чтобы автоматическая облегченная миграция показывала ее прогресс, как это происходит при ручной миграции.