My Core Data document-based application crashes on "save as". The problem seems similar to the one described in the cocoa-dev thread titled "NSPersistentDocument objects "gutted" after Duplicate, Rename in 10.9"
The key differences being that:
- I target and run on OS X 10.10 Yosemite
- Use "Save As" rather than Duplicate
- The crash occurs earlier. During the MOC save
The problem affects even the simplest NSPersistentDocument. It has been around at least since 2014. Thus I hope for others to have encountered the same problem and have a workaround you care to share.
My sample project uses a single entity with a single attribute. It has a table view to display all instances of the entity and a button to create a new one. I strayed from the default template only to disable autosavesInPlace.
The steps to reproduce the crash are:
- Build and run on Yosemite. The bug appears to have been fixed in El Capitan
- Create a new document
- Insert a new object
- Save the document
- Close the document
- Re-open the document
- Change the value of the attribute in the table
- Use "Save As" to save under a new name
On OS X Yosemite this always crashes with the following backtrace:
_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 ()
Edit 1. Possible workaround:
I can patch around the crash by preventing the original managed object context from being saved during the “save as” operation. After “save as” I immediately close the existing document and re-open the document from the new location. It’s all very ugly and may break other NSPersistentDocument behavior.
Edit 2. Above workaround loses unsaved changes
Preventing the original managed object context from saving does avoid the crash. The end-result however is a copy of the document in its last saved state. Unsaved changes are lost.
Edit 3. Gutted snapshot
By the time the old managed object context tries to save changes to the new file, the object snapshot no longer knows its entity <_CDSnapshot_Entity_: 0x600001f3cfd0> (entity: (null); id: 0x40000b <x-coredata://83B64FD3-B5B9-44CB-976D-54C0326FDFF5/Entity/p1> ; data: (null))
. I don’t see any instance variable backing -[_CDSnapshot entity]
. I assume it should find that from the object ID.