首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSPersistentDocument在“另存为”上崩溃

NSPersistentDocument在“另存为”上崩溃
EN

Stack Overflow用户
提问于 2016-04-19 10:07:10
回答 1查看 341关注 0票数 1

基于核心数据文档的应用程序在“另存为”上崩溃。这个问题似乎类似于可可开发线程"NSPersistentDocument对象在重复后被“删除”,在10.9中重命名“中描述的问题。

主要的区别是:

  • 我在OSX10.10 Yosemite上瞄准并运行
  • 使用“另存为”而不是重复
  • 坠机时间较早。在MOC保存期间

这个问题甚至影响到最简单的NSPersistentDocument。至少从2014年起就已经出现了。因此,我希望其他人已经遇到了同样的问题,并有一个解决办法,你愿意分享。

我的样本工程使用一个具有单个属性的实体。它有一个表视图来显示实体的所有实例,并有一个按钮来创建新的实例。我偏离了默认模板,只禁用了autosavesInPlace。

再现坠机的步骤如下:

  1. 在约塞米蒂建造和运行。这种虫子似乎是在埃尔卡皮坦修复的。
  2. 创建新文档
  3. 插入新对象
  4. 保存文档
  5. 关闭文档
  6. 重新打开文件
  7. 更改表中属性值
  8. 使用“另存为”以新名称保存

在上,总是会出现以下回溯:

代码语言:javascript
复制
_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行为。

上面的解决方案会丢失未保存的更改()。

防止原始托管对象上下文保存确实可以避免崩溃。但是,最终结果是处于最后保存状态的文档的副本。未保存的更改丢失。

编辑3.删除快照

当旧的托管对象上下文试图保存对新文件的更改时,对象快照不再知道其实体<_CDSnapshot_Entity_: 0x600001f3cfd0> (entity: (null); id: 0x40000b <x-coredata://83B64FD3-B5B9-44CB-976D-54C0326FDFF5/Entity/p1> ; data: (null))。我没有看到任何实例变量支持-[_CDSnapshot entity]。我想它应该从对象ID中找到它。

EN

回答 1

Stack Overflow用户

发布于 2016-04-27 12:27:02

我已经想出了一个适合我的用例的解决方案。

代码语言:javascript
复制
- (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复制一个文件。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36715201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档