gpt4 book ai didi

macos - NSPersistentDocument 在 “save as” 上崩溃

转载 作者:行者123 更新时间:2023-12-03 17:10:01 32 4
gpt4 key购买 nike

我的基于 Core Data 文档的应用程序在“另存为”时崩溃。该问题似乎与标题为“NSPersistentDocument objects "gutted" after Duplicate, Rename in 10.9”的 cocoa-dev 线程中描述的问题类似

主要区别在于:

  • 我以 OS X 10.10 Yosemite 为目标并运行
  • 使用“另存为”而不是“复制”
  • 崩溃发生得更早。 MOC 保存期间

这个问题甚至会影响最简单的 NSPersistentDocument。它至少从 2014 年就已经存在了。因此,我希望其他人也遇到过同样的问题,并有一个您愿意分享的解决方法。

我的sample project使用具有单个属性的单个实体。它有一个用于显示实体的所有实例的 TableView 和一个用于创建新实例的按钮。我偏离了默认模板只是为了禁用 autosavesInPlace。

重现崩溃的步骤是:

  1. 在 Yosemite 上构建并运行。该错误似乎已在 El 中修复船长
  2. 创建新文档
  3. 插入新对象
  4. 保存文档
  5. 关闭文档
  6. 重新打开文档
  7. 更改表中属性的值
  8. 使用“另存为”以新名称保存

在 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] 。我认为它应该从对象 ID 中找到它。

最佳答案

我想出了一个似乎适合我的用例的解决方法。

- (BOOL)writeToURL:(NSURL *)absoluteURL
ofType:(NSString *)typeName
forSaveOperation:(NSSaveOperationType)saveOperation
originalContentsURL:(NSURL *)absoluteOriginalContentsURL
error:(NSError **)error
{
if ((saveOperation == NSSaveAsOperation) && (absoluteOriginalContentsURL != nil)) {
NSFileManager *fileManager = [NSFileManager defaultManager];

if (![fileManager copyItemAtURL:absoluteOriginalContentsURL toURL:absoluteURL error:error]) {
return NO;
}

NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator = managedObjectContext.persistentStoreCoordinator;
NSPersistentStore *store = [persistentStoreCoordinator persistentStoreForURL:absoluteOriginalContentsURL];

[persistentStoreCoordinator setURL:absoluteURL forPersistentStore:store];

if (![managedObjectContext save:error]) {
return NO;
}

return YES;
}

return [super writeToURL:absoluteURL
ofType:typeName
forSaveOperation:saveOperation
originalContentsURL:absoluteOriginalContentsURL
error:error];
}

另存为时,我将旧文档复制到新(临时)位置。然后,我在持久性存储上设置新的 URL,并让托管对象上下文将挂起的更改保存到该新文档。

NSPersistentDocument 负责生成作为 absoluteURL 传入的临时 URL,将保存的文件移动到新位置,并在保存完成后调用 setFileURL:

我已禁用支持文档的 SQLite 存储上的日记功能。因此,我只需要复制 absoluteOriginalContentsURL 处的一个文件。

关于macos - NSPersistentDocument 在 “save as” 上崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36715201/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com