Несколько лет назад Core Data добавила в модели данных функцию, которая при нулевом коде при сохранении автоматически объединяет новые вставки с существующими объектами, когда определенные вами атрибуты имеют равные значения. Эта функция называется Уникальное ограничение . Очень хорошо. Но, похоже, это вызывает исключения, когда происходит это слияние.
Я создал небольшой проект , демонстрирующий эту функцию , который был написан Захари Орром в 2015 году в Objective-C. Этот проект обсуждается в первом ответе на этот вопрос о переполнении стека , в котором также есть симпатичное видео, показывающее слияние объектов, когда пользователь нажимает Сохранить . Мой форк этого проекта преобразует его в Swift 5.
Выполняя проект Objective-C или Swift 5 в iOS 12, я могу воспроизвести видео Захария, показывающее правильную работу, только если я отключу свою точку останова пользователя на objc_exception_throw
(или Все исключения Objective-C ). Итак, либо Захари не включил эту точку останова, когда записывал это видео, либо эти исключения не возникали в iOS 9.
Если эта точка останова включена, после нажатия кнопки + достаточное количество раз, чтобы добавить повторяющиеся записи, а затем нажатия Сохранить , в ходе выполнения NSManagedObjectContext.save()
возникает несколько исключений. В частности, если я добавлю N повторяющихся записей, я получу N + 1 Нарушение ограничения исключения и N + 2 Сбой оптимистической блокировки исключения. (Чтобы увидеть описание исключения, когда оно прерывается, выберите objc_exception_throw
вверху стека вызовов, затем введите команду po $arg1
в консоли отладчика.) Примеры:
(lldb) po $arg1
Constraint violation
(null)
(lldb) po $arg1
optimistic locking failure
(null)
После того, как я прикажу отладчику продолжить (N + 1) + (N + 2) раза, приложение продолжит работу, дубликаты будут объединены, как и ожидалось, и все в порядке.
Общеизвестно, что такие исключения обычно происходят из-за неправильной установки политики слияния в контексте. Но в обоих проектах контекст имеет NSMergeByPropertyObjectTrumpMergePolicy
. Я убедился, что это работает, напечатав выражение
context.mergePolicy == NSMergeByPropertyObjectTrumpMergePolicy
непосредственно перед вызовом save (). Это печатает true
.
Похоже, @ KMC спрашивал о таких исключениях в 2017 , но так и не получил ответа.
Обновление: я отправил это в Apple Bug Reporter: 50726397. Во время ожидания ответа, что-то не так в моем коде, или дети просто не беспокоятся об исключениях в наши дни?