Приложение My Core Data, основанное на документах, аварийно завершает работу при «сохранить как». Проблема похожа на ту, что описана в теме какао-dev под названием "Объекты NSPersistentDocument "выпотрошены" после дублирования, переименования в 10.9"
Ключевые отличия заключаются в том, что:
- Я ориентируюсь и работаю на OS X 10.10 Yosemite
- Используйте «Сохранить как», а не дублировать
- Сбой происходит раньше. Во время сохранения MOC
Проблема затрагивает даже самый простой NSPersistentDocument. Он существует по крайней мере с 2014 года. Поэтому я надеюсь, что другие столкнулись с той же проблемой и у вас есть обходной путь, которым вы хотите поделиться.
В моем примере проекта используется один объект с одним атрибутом. Он имеет табличное представление для отображения всех экземпляров объекта и кнопку для создания нового. Я отклонился от шаблона по умолчанию только для того, чтобы отключить автосохранение на месте.
Шаги для воспроизведения сбоя:
- Создавайте и запускайте на Yosemite. Ошибка, похоже, была исправлена в El Capitan.
- Создать новый документ
- Вставить новый объект
- Сохраните документ
- Закрыть документ
- Повторно открыть документ
- Изменить значение атрибута в таблице
- Используйте «Сохранить как», чтобы сохранить под новым именем
В OS X Yosemite всегда происходит сбой со следующей трассировкой:
_propertyAtIndexForEntityDescription ()
snapshot_get_value_as_object ()
-[NSManagedObject(_NSInternalMethods) _validatePropertiesWithError:] ()
-[NSManagedObject(_NSInternalMethods) _validateForSave:] ()
-[NSManagedObject validateForUpdate:] ()
-[NSManagedObjectContext(_NSInternalAdditions) _validateObjects:forOperation:error:exhaustive:forSave:] ()
-[NSManagedObjectContext(_NSInternalAdditions) _validateChangesForSave:] ()
-[NSManagedObjectContext(_NSInternalChangeProcessing) _prepareForPushChanges:] ()
-[NSManagedObjectContext save:] ()
-[NSPersistentDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:] ()
-[NSDocument _writeSafelyToURL:ofType:forSaveOperation:forceTemporaryDirectory:error:] ()
-[NSDocument _writeSafelyToURL:ofType:forSaveOperation:error:] ()
-[NSDocument writeSafelyToURL:ofType:forSaveOperation:error:] ()
-[NSPersistentDocument writeSafelyToURL:ofType:forSaveOperation:error:] ()
__66-[NSDocument saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_22353 ()
__66-[NSDocument saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke2350 ()
__66-[NSDocument saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_22222 ()
__110-[NSFileCoordinator(NSPrivate) _coordinateReadingItemAtURL:options:writingItemAtURL:options:error:byAccessor:]_block_invoke428 ()
-[NSFileCoordinator(NSPrivate) _invokeAccessor:orDont:andRelinquishAccessClaim:] ()
-[NSFileCoordinator(NSPrivate) _coordinateReadingItemAtURL:options:writingItemAtURL:options:error:byAccessor:] ()
-[NSDocument _fileCoordinator:coordinateReadingContentsAndWritingItemAtURL:byAccessor:] ()
-[NSDocument _fileCoordinator:asynchronouslyCoordinateReadingContentsAndWritingItemAtURL:byAccessor:] ()
__66-[NSDocument saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke2221 ()
-[NSDocument _prepareToSaveToURL:forSaveOperation:completionHandler:] ()
__66-[NSDocument saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke ()
-[NSDocument continueFileAccessUsingBlock:] ()
-[NSDocument _performFileAccessOnMainThread:usingBlock:] ()
-[NSDocument performAsynchronousFileAccessUsingBlock:] ()
-[NSDocument saveToURL:ofType:forSaveOperation:completionHandler:] ()
__85-[NSDocument saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:]_block_invoke_2 ()
-[NSDocument _commitEditingThenContinue:] ()
__62-[NSPersistentDocument _documentEditor:didCommit:withContext:]_block_invoke ()
Изменить 1. Возможный обходной путь:
Я могу устранить сбой, предотвратив сохранение исходного контекста управляемого объекта во время операции «сохранить как». После «сохранить как» я сразу же закрываю существующий документ и снова открываю документ из нового места. Все это очень уродливо и может сломать другое поведение NSPersistentDocument.
Редактировать 2. Приведенный выше обходной путь теряет несохраненные изменения
Предотвращение сохранения исходного контекста управляемого объекта позволяет избежать сбоя. Однако конечным результатом является копия документа в его последнем сохраненном состоянии. Несохраненные изменения теряются.
Редактировать 3. Выпотрошенный снимок
К тому времени, когда старый контекст управляемого объекта попытается сохранить изменения в новом файле, моментальный снимок объекта уже не знает свою сущность <_CDSnapshot_Entity_: 0x600001f3cfd0> (entity: (null); id: 0x40000b <x-coredata://83B64FD3-B5B9-44CB-976D-54C0326FDFF5/Entity/p1> ; data: (null))
. Я не вижу никакой переменной экземпляра, поддерживающей -[_CDSnapshot entity]
. Я предполагаю, что он должен найти это по идентификатору объекта.
validateForUpdate:
. Интересно, что произойдет, если вы вызовете это непосредственно на объекте документа. - person Phillip Mills   schedule 19.04.2016validateForUpdate:
перед вызовом[super writeToURL:ofType:forSaveOperation:originalContentsURL: error:]
. Я думаю, что проблема возникает, когда существующий контекст управляемого объекта вызывается при записи в новое место. Похоже, что свойства управляемых объектов больше не доступны в этот момент. - person Pierre Bernard   schedule 19.04.2016NSManagedObject
. Я обнаружил, что-[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:]
создает новый экземпляр моего управляемого объекта в новом контексте управляемого объекта. Позже этот новый управляемый объект становится неисправным и освобождается. Затем-[NSManagedObjectContext save:]
вызываетсяvalidateForSave:
для исходного управляемого объекта. - person Pierre Bernard   schedule 19.04.2016-[super writeToURL:ofType:forSaveOperation:originalContentsURL:error:]
контекст управляемого объекта все еще был связан со старым URL-адресом файла. Доступ к атрибутам управляемых объектов не вызывает проблем. В-[NSManagedObject save]
контекст управляемого объекта по-прежнему связан с новым URL-адресом файла. Доступ к атрибутам или попытки обновить объекты завершаются неудачей. Я думаю, что снимок исчез. - person Pierre Bernard   schedule 19.04.2016