Подтвердить что ты не робот

EXC_BAD_ACCESS для mergeChangesFromContextDidSaveNotification

Мы пытаемся отлаживать проблему с несколькими контентами/потоками Core Data, в которой объединение уведомления о сохранении Core Data в наш основной поток NSManagedObjectContext вызывает спорадическое сбой приложения. Это приводит к сбою ~ 2% от наших сеансов приложений, и мы не понимаем, как это решить. Мы были бы очень признательны за любые рекомендации или общие рекомендации о том, что может привести к этой катастрофе.

У нас есть настройка Core Data, которая выглядит так:

Core Data Stack Нотабене Это стандартный стек Core Data в Magical Record v2.3, созданный с помощью [MagicalRecord setupAutoMigratingCoreDataStack]

Это сценарий, в котором наше приложение терпит крах:

  • Запрос HTTP возвращает JSON
  • JSON анализируется на NSManagedObject (некоторые новые сущности, некоторые обновленные объекты) в Контекст сохранения корня
  • Контекст сохранения корня сохраняет в постоянном хранилище
  • NSManagedObjectContextDidSaveNotification транслируется базовыми данными. По умолчанию используется контекст в главной очереди и вызывает mergeChangesFromContextDidSaveNotification: с NSDictionary изменений в основном потоке.
  • Он вылетает, когда objectID отправляется на недопустимый объект (скорее всего, NSManagedObject был освобожден).

Это происходит внутри частной реализации NSManagedObjectContext mergeChangesFromContextDidSaveNotification:, поэтому мы не можем видеть, что на самом деле произошло здесь неправильно; все, что мы можем сказать в этой точке, что объект, который должен существовать, не делает.

enter image description here

Это происходит только при небольшом проценте данных Core Data, что указывает на то, что это не может быть фундаментальным недостатком в нашем стеке Core Data → API. Более того, нет никаких указаний на то, что размер или тип изменений (вставки/обновления/удаления) в контексте изменений оказывают какое-либо влияние на вероятность сбоя.

4b9b3361

Ответ 1

Прошло некоторое время, так как этот вопрос был опубликован, и после его повторного открытия я хотел бы ответить на свой вопрос ради других, кто нашел эту тему.

В моих обстоятельствах я перенесла большую базу кода из sibling NSManagedObjectContexts, обновленную через NSManagedObjectContextDidSaveNotification. Однако проблема не имела в этом никакого отношения, хотя это и вызывало проблему.

Настоящей причиной этого были места, где были старые части кода, которые были установлены предыдущими инженерами, которые установили KVO на NSManagedObject и их свойства. Выяснилось, что KVO на объектах Core Data на самом деле очень плохая идея.

Точнее, оказалось, что это произошло, когда KVO был настроен на сущности и либо объект, либо цель отношения к этому объекту была удалена из NSPersistentStore. Это второе условие, казалось, не было единственной причиной проблемы, но определенно было очень заметной причиной в моей ситуации.

Извлеченный урок:

  • Используйте выбранный контроллер результатов, когда вам нужно. KVO не является удобным ярлыком, и вам не следует избегать переноса изворотливого кода Core Data KVO на NSFetchedResultsControllers или другой разумной альтернативы, поскольку промедление просто повредит вам.
  • Многопоточные базовые данные - это сложный, но очень полезный навык, чтобы стать экспертом. Знание стека Core Data и нюансов и ограничений многопоточности Core Data абсолютно стоит всех душевных страданий.

Ответ 2

В документации NSManagedObjectContextDidSaveNotification указано, что:

"Вы можете передать объект уведомления в mergeChangesFromContextDidSaveNotification: в другом потоке, однако вы не должны использовать управляемый объект в словаре пользовательской информации непосредственно в другом потоке. Для получения дополнительной информации см. Concurrency с основными данными в основных данных Руководство по программированию."

Может, это и есть проблема? Я бы удостоверился, что объект u получит из уведомления, который сохраняется в Контексте По умолчанию в том же потоке, который был отправлен Root.

Ответ 3

Одна из возможностей заключается в том, что ваш постоянный магазин поврежден и находится в противоречивом состоянии. Если это произойдет, генерируется код ошибки, с которым Magical Record не обязательно справляется. Это может быть источником ряда трудно-повторяющихся явно-случайных сбоев, связанных с магической записью (и может быть или не может считаться ошибкой Magical Record).

Стоит прочитать "Волшебная запись", которая затрагивает темы здесь (тот же выпуск) и здесь (другая проблема, но может быть аналогичной причиной). Когда я сталкивался с этими проблемами, мне удалось сделать некоторые временные исправления исправлений, следуя различным подсказкам в этих потоках, но в конечном итоге я решил удалить свою зависимость от Magical Record, и с тех пор у меня не было проблем.