未为saveAs NSPersistentDocument调用configurePersistentStoreCoordinator [英] configurePersistentStoreCoordinator not called for saveAs NSPersistentDocument

查看:65
本文介绍了未为saveAs NSPersistentDocument调用configurePersistentStoreCoordinator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在保存NSPersistentDocument时遇到奇怪的行为。我可以创建一个自动保存的新文档。但是当我保存它时,调用了 write(to:ofType:for:absoluteOriginalContentsURL:),但它变成了 configurePersistentStoreCoordinator(for:ofType:modelConfiguration: storeOptions:)没有被调用。不幸的是,我需要配置存储。原因是我需要将NSColor注册为可解码的 options [NSBinaryStoreSecureDecodingClasses] = NSSet(对象:NSColor.self)

I experience an odd behaviour regarding saving an NSPersistentDocument. I can create a new document which is autosaved without an issue. But when I save it write(to: ofType: for: absoluteOriginalContentsURL:) is called but it turns to that configurePersistentStoreCoordinator(for: ofType: modelConfiguration: storeOptions:) isn't called. That is unfortunate as I need to configure the store. Reason is that I need to register NSColor as decodable options[NSBinaryStoreSecureDecodingClasses] = NSSet(object: NSColor.self).

最初的尝试是自己叫它,但是那没带我到任何地方。我自己叫它并没有按预期注册设置。

First attempt was to call it myself, but that didn't lead me anywhere. Calling it myself didn't register the settings as expected.

NSPersistentDocument中的代码如下:

Code in my NSPersistentDocument looks like this:

 override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {
        Swift.print("VTDocment.configurePersistentStoreCoordinator for \(url.lastPathComponent)")
        var options = addOptions(to: storeOptions)
        try super.configurePersistentStoreCoordinator(for: url, ofType: fileType, modelConfiguration: configuration, storeOptions: options)
    }      

    func addOptions(to: [String : Any]?) -> [String : Any] {
        var options = to != nil ? to! : [String:Any]()
        if #available(OSX 10.13, *) {
            options[NSBinaryStoreSecureDecodingClasses] = NSSet(object: NSColor.self)
        }
        options[NSMigratePersistentStoresAutomaticallyOption] = true
        options[NSInferMappingModelAutomaticallyOption] = true
        return options
    } 

override func write(to url: URL, ofType typeName: String, for saveOperation: NSDocument.SaveOperationType, originalContentsURL absoluteOriginalContentsURL: URL?) throws {
    try self.configurePersistentStoreCoordinator(for: url, ofType: typeName, modelConfiguration: "Document")
    do {
        Swift.print("Now... VTDocment.write to \(url.lastPathComponent)")
        try super.write(to: url, ofType: typeName, for: saveOperation, originalContentsURL: absoluteOriginalContentsURL)
    } catch {
        Swift.print("VTDocment.write error: \(error)")
    }
}

恢复lt是以下输出(第二个configurePersistentStoreCoordinator输出在通过菜单命令另存为之后开始):

Result is the following output (second configurePersistentStoreCoordinator output is starting after the save as through menu command):

VTDocment.configurePersistentStoreCoordinator for Unsaved Visual Thinking with IBIS Document 12.ibisVT
VTDocment.configurePersistentStoreCoordinator for test.ibisVT
Now... VTDocment.write to test.ibisVT
value for key 'NS.objects' was of unexpected class 'NSColor'. Allowed classes are '{(
    NSNumber,
    NSString,
    NSCalendarDate,
    NSOrderedSet,
    NSDecimalNumber,
    NSUUID,
    NSDate,
    NSSet,
    NSNull,
    NSURL,
    NSData,
    NSDictionaryMapNode,
    NSDictionary,
    NSArray
)}'.
(null)

105827995370488

2018-02-09 05:53:52.250312+0100 Visual Thinking with IBIS[42589:19295813] -[NSException initialize]: unrecognized selector sent to instance 0x60400025d7c0
value for key 'NS.objects' was of unexpected class 'NSColor'. Allowed classes are '{(
    NSNumber,
    NSString,
    NSCalendarDate,
    NSOrderedSet,
    NSDecimalNumber,
    NSUUID,
    NSDate,
    NSSet,
    NSNull,
    NSURL,
    NSData,
    NSDictionaryMapNode,
    NSDictionary,
    NSArray
)}'.

编辑
感谢您的提问@Tora!这是一个相关的堆栈跟踪。它不是来自同一会话,而是导致相同的结果。

EDIT Thanks for the questions @Tora! Here is a related stack trace. It's not from the same session but leading to the same result.

    0   CoreFoundation                      0x00007fff40f9ffcb __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x00007fff67c41c76 objc_exception_throw + 48
2   Foundation                          0x00007fff430ef08f -[NSCoder(Exceptions) __failWithExceptionName:errorCode:format:] + 0
3   Foundation                          0x00007fff430ef20c -[NSCoder(Exceptions) __failWithExceptionName:errorCode:format:] + 381
4   Foundation                          0x00007fff43017555 -[NSCoder _validateAllowedClass:forKey:allowingInvocations:] + 239
5   Foundation                          0x00007fff42fd948c _decodeObjectBinary + 1944
6   Foundation                          0x00007fff42fdaa6f -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 1945
7   Foundation                          0x00007fff42fde8c5 -[NSArray(NSArray) initWithCoder:] + 202
8   Foundation                          0x00007fff42fd9523 _decodeObjectBinary + 2095
9   Foundation                          0x00007fff42fd8bee _decodeObject + 417
10  Foundation                          0x00007fff42ff171b -[NSKeyedUnarchiver decodeObjectOfClasses:forKey:] + 409
11  CoreData                            0x00007fff40b77491 -[NSDictionaryMapNode initWithCoder:] + 97
12  Foundation                          0x00007fff42fd9523 _decodeObjectBinary + 2095
13  Foundation                          0x00007fff42fdaa6f -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 1945
14  Foundation                          0x00007fff42fd9de8 -[NSDictionary(NSDictionary) initWithCoder:] + 202
15  Foundation                          0x00007fff42fd9523 _decodeObjectBinary + 2095
16  Foundation                          0x00007fff42fd8bee _decodeObject + 417
17  Foundation                          0x00007fff42ff171b -[NSKeyedUnarchiver decodeObjectOfClasses:forKey:] + 409
18  CoreData                            0x00007fff40bcfcc2 -[NSBinaryObjectStoreFile readBinaryStoreFromData:originalPath:error:] + 994
19  CoreData                            0x00007fff40bd019a -[NSBinaryObjectStoreFile readFromFile:error:] + 474
20  CoreData                            0x00007fff40aed247 -[NSDictionaryStoreMap initWithStore:fromPath:] + 215
21  CoreData                            0x00007fff40b75bd3 -[NSBinaryObjectStore initWithPersistentStoreCoordinator:configurationName:URL:options:] + 739
22  CoreData                            0x00007fff40b56e35 __91-[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]_block_invoke + 1845
23  CoreData                            0x00007fff40b69132 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 210
24  CoreData                            0x00007fff40b52f75 _perform + 213
25  CoreData                            0x00007fff40a7d2cf -[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:] + 559
26  CoreData                            0x00007fff40b596e4 __84-[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:]_block_invoke + 1284
27  CoreData                            0x00007fff40b69132 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 210
28  libdispatch.dylib                   0x00007fff687f7d50 _dispatch_client_callout + 8
29  libdispatch.dylib                   0x00007fff6880b1d6 _dispatch_queue_barrier_sync_invoke_and_complete + 60
30  CoreData                            0x00007fff40b52f62 _perform + 194
31  CoreData                            0x00007fff40b590ef -[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:] + 351
32  AppKit                              0x00007fff3ebc8fd6 -[NSPersistentDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:] + 2367
33  Visual Thinking with IBIS           0x000000010003edb2 _T025Visual_Thinking_with_IBIS10VTDocumentC5writey10Foundation3URLV2to_SS6ofTypeSo10NSDocumentC013SaveOperationK0O3forAGSg016originalContentsH0tKF + 1570
34  Visual Thinking with IBIS           0x000000010003f22c _T025Visual_Thinking_with_IBIS10VTDocumentC5writey10Foundation3URLV2to_SS6ofTypeSo10NSDocumentC013SaveOperationK0O3forAGSg016originalContentsH0tKFTo + 284
35  AppKit                              0x00007fff3f0996aa -[NSDocument(NSDocumentSaving) _writeSafelyToURL:ofType:forSaveOperation:forceTemporaryDirectory:error:] + 870
36  AppKit                              0x00007fff3f09a394 -[NSDocument(NSDocumentSaving) _writeSafelyToURL:ofType:forSaveOperation:error:] + 28
37  AppKit                              0x00007fff3ebc9eb3 -[NSPersistentDocument writeSafelyToURL:ofType:forSaveOperation:error:] + 446
38  AppKit                              0x00007fff3f0a5294 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_2.1146 + 238
39  AppKit                              0x00007fff3f0a5197 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke.1143 + 454
40  AppKit                              0x00007fff3f0a33ff __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_3.999 + 1962
41  AppKit                              0x00007fff3eae0eb4 -[NSDocument(NSDocumentSerializationAPIs) continueFileAccessUsingBlock:] + 238
42  AppKit                              0x00007fff3f0a04b9 __119-[NSDocument(NSDocumentSaving) _fileCoordinator:asynchronouslyCoordinateReadingContentsAndWritingItemAtURL:byAccessor:]_block_invoke_2 + 94
43  AppKit                              0x00007fff3ea5f8c0 __62-[NSDocumentController(NSInternal) _onMainThreadInvokeWorker:]_block_invoke.2153 + 157
44  CoreFoundation                      0x00007fff40f3858c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
45  CoreFoundation                      0x00007fff40f1b043 __CFRunLoopDoBlocks + 275
46  CoreFoundation                      0x00007fff40f1ae08 __CFRunLoopRun + 3128
47  CoreFoundation                      0x00007fff40f19f43 CFRunLoopRunSpecific + 483
48  HIToolbox                           0x00007fff40231e26 RunCurrentEventLoopInMode + 286
49  HIToolbox                           0x00007fff40231b96 ReceiveNextEventCommon + 613
50  HIToolbox                           0x00007fff40231914 _BlockUntilNextEventMatchingListInModeWithFilter + 64
51  AppKit                              0x00007fff3e4fcf5f _DPSNextEvent + 2085
52  AppKit                              0x00007fff3ec92b4c -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
53  AppKit                              0x00007fff3e4f1d6d -[NSApplication run] + 764
54  AppKit                              0x00007fff3e4c0f1a NSApplicationMain + 804
55  Visual Thinking with IBIS           0x0000000100019bed main + 13
56  libdyld.dylib                       0x00007fff68831115 start + 1

非常感谢。

更新
来自Tora的解决方案(通过方法转换)效果很好。但是,有时(不确定何时)可能导致相同的问题。这是更新的堆栈跟踪。这很神秘。 :-)

Update Solution from Tora (via method swizzling) works fine. However, sometimes (not sure when) the same issue can result. Here is the updated stack trace. This is mysterious. :-)

0   CoreFoundation                      0x00007fff40f9ffcb __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x00007fff67c41c76 objc_exception_throw + 48
2   Foundation                          0x00007fff430ef08f -[NSCoder(Exceptions) __failWithExceptionName:errorCode:format:] + 0
3   Foundation                          0x00007fff430ef20c -[NSCoder(Exceptions) __failWithExceptionName:errorCode:format:] + 381
4   Foundation                          0x00007fff43017555 -[NSCoder _validateAllowedClass:forKey:allowingInvocations:] + 239
5   Foundation                          0x00007fff42fd948c _decodeObjectBinary + 1944
6   Foundation                          0x00007fff42fdaa6f -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 1945
7   Foundation                          0x00007fff42fde8c5 -[NSArray(NSArray) initWithCoder:] + 202
8   Foundation                          0x00007fff42fd9523 _decodeObjectBinary + 2095
9   Foundation                          0x00007fff42fd8bee _decodeObject + 417
10  Foundation                          0x00007fff42ff171b -[NSKeyedUnarchiver decodeObjectOfClasses:forKey:] + 409
11  CoreData                            0x00007fff40b77491 -[NSDictionaryMapNode initWithCoder:] + 97
12  Foundation                          0x00007fff42fd9523 _decodeObjectBinary + 2095
13  Foundation                          0x00007fff42fdaa6f -[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:] + 1945
14  Foundation                          0x00007fff42fd9de8 -[NSDictionary(NSDictionary) initWithCoder:] + 202
15  Foundation                          0x00007fff42fd9523 _decodeObjectBinary + 2095
16  Foundation                          0x00007fff42fd8bee _decodeObject + 417
17  Foundation                          0x00007fff42ff171b -[NSKeyedUnarchiver decodeObjectOfClasses:forKey:] + 409
18  CoreData                            0x00007fff40bcfcc2 -[NSBinaryObjectStoreFile readBinaryStoreFromData:originalPath:error:] + 994
19  CoreData                            0x00007fff40bd019a -[NSBinaryObjectStoreFile readFromFile:error:] + 474
20  CoreData                            0x00007fff40aed247 -[NSDictionaryStoreMap initWithStore:fromPath:] + 215
21  CoreData                            0x00007fff40b75bd3 -[NSBinaryObjectStore initWithPersistentStoreCoordinator:configurationName:URL:options:] + 739
22  CoreData                            0x00007fff40b56e35 __91-[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]_block_invoke + 1845
23  CoreData                            0x00007fff40b69132 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 210
24  CoreData                            0x00007fff40b52f75 _perform + 213
25  CoreData                            0x00007fff40a7d2cf -[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:] + 559
26  CoreData                            0x00007fff40b596e4 __84-[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:]_block_invoke + 1284
27  CoreData                            0x00007fff40b69132 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 210
28  libdispatch.dylib                   0x00007fff687f7d50 _dispatch_client_callout + 8
29  libdispatch.dylib                   0x00007fff6880b1d6 _dispatch_queue_barrier_sync_invoke_and_complete + 60
30  CoreData                            0x00007fff40b52f62 _perform + 194
31  CoreData                            0x00007fff40b590ef -[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:] + 351
32  AppKit                              0x00007fff3ebc8fd6 -[NSPersistentDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:] + 2367
33  Visual Thinking with IBIS           0x00000001000404a2 _T025Visual_Thinking_with_IBIS10VTDocumentC5writey10Foundation3URLV2to_SS6ofTypeSo10NSDocumentC013SaveOperationK0O3forAGSg016originalContentsH0tKF + 1570
34  Visual Thinking with IBIS           0x000000010004091c _T025Visual_Thinking_with_IBIS10VTDocumentC5writey10Foundation3URLV2to_SS6ofTypeSo10NSDocumentC013SaveOperationK0O3forAGSg016originalContentsH0tKFTo + 284
35  AppKit                              0x00007fff3f0996aa -[NSDocument(NSDocumentSaving) _writeSafelyToURL:ofType:forSaveOperation:forceTemporaryDirectory:error:] + 870
36  AppKit                              0x00007fff3f09a394 -[NSDocument(NSDocumentSaving) _writeSafelyToURL:ofType:forSaveOperation:error:] + 28
37  AppKit                              0x00007fff3ebc9eb3 -[NSPersistentDocument writeSafelyToURL:ofType:forSaveOperation:error:] + 446
38  AppKit                              0x00007fff3f0a5294 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_2.1146 + 238
39  AppKit                              0x00007fff3f0a5197 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke.1143 + 454
40  AppKit                              0x00007fff3f0a33ff __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_3.999 + 1962
41  AppKit                              0x00007fff3eae0eb4 -[NSDocument(NSDocumentSerializationAPIs) continueFileAccessUsingBlock:] + 238
42  AppKit                              0x00007fff3f0a04b9 __119-[NSDocument(NSDocumentSaving) _fileCoordinator:asynchronouslyCoordinateReadingContentsAndWritingItemAtURL:byAccessor:]_block_invoke_2 + 94
43  AppKit                              0x00007fff3ea5f8c0 __62-[NSDocumentController(NSInternal) _onMainThreadInvokeWorker:]_block_invoke.2153 + 157
44  CoreFoundation                      0x00007fff40f3858c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
45  CoreFoundation                      0x00007fff40f1b043 __CFRunLoopDoBlocks + 275
46  CoreFoundation                      0x00007fff40f1ae08 __CFRunLoopRun + 3128
47  CoreFoundation                      0x00007fff40f19f43 CFRunLoopRunSpecific + 483
48  HIToolbox                           0x00007fff40231e26 RunCurrentEventLoopInMode + 286
49  HIToolbox                           0x00007fff40231b96 ReceiveNextEventCommon + 613
50  HIToolbox                           0x00007fff40231914 _BlockUntilNextEventMatchingListInModeWithFilter + 64
51  AppKit                              0x00007fff3e4fcf5f _DPSNextEvent + 2085
52  AppKit                              0x00007fff3ec92b4c -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
53  AppKit                              0x00007fff3e4f1d6d -[NSApplication run] + 764
54  AppKit                              0x00007fff3e4c0f1a NSApplicationMain + 804
55  Visual Thinking with IBIS           0x000000010001a3dd main + 13
56  libdyld.dylib                       0x00007fff68831115 start + 1


推荐答案

另一个更简单的解决方法:

以下代码有一个错误。请参考下面引用的错误修复版本。

The following code has a bug. Please refer to the bug fixed version cited below.

extension NSPersistentStoreCoordinator {

  @objc func x_migratePersistentStore(_ store: NSPersistentStore, to URL: URL, options: [AnyHashable : Any]? = nil, withType storeType: String) throws -> NSPersistentStore {
    var opt: [AnyHashable : Any] = options ?? [:]

    if #available(OSX 10.13, *) {
      opt[NSBinaryStoreSecureDecodingClasses] = NSSet(array: [ NSColor.self ])
    }

    return try x_migratePersistentStore(store, to: URL, options: opt, withType: storeType)
  }

}

class Document: NSPersistentDocument {

  override init() {
    super.init()

    let s1 = #selector(NSPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:))
    let s2 = #selector(NSPersistentStoreCoordinator.x_migratePersistentStore(_:to:options:withType:))
    let m1 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s1)!
    let m2 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s2)!
    method_exchangeImplementations(m1, m2)
  }

  override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {
    // keep yours
  }

}

已添加:

此变通办法将是一个切实可行的解决方案,直到他们增强 NSPersistentDocument .write(to ...)来考虑选项,或者它们实现了其他方式来处理选项。这些选项将提供给 NSPersistentStoreCoordinator.migratePersistentStore(...),然后用于实例化 NSPersistentStore

This workaround is going to be a practical solution until they enhance NSPersistentDocument.write(to...) to take into account of options or they implement other means to handle options. Those options will be given to NSPersistentStoreCoordinator.migratePersistentStore(...) and then be used to instantiate NSPersistentStore.

错误的固定版本:

上述解决方法中存在一个错误。打开文档文件,创建新文件,进行更改,等待自动保存的文档等待30秒,关闭它们和/或将它们随机保存时,都会引起初始错误。

There was a bug in the preceding workaround. Opening document files, creating new files, making changes, waiting for thirty second to the document being auto-saved, closing them, and/or save-as-ing them randomly would cause the initial error. Reported by Wizard of Kneup.

这里是一个固定的版本,使用单例来确保仅应用一次毛毛雨。

Here is a fixed version using singleton to make sure swizzling is applied only once.

extension NSPersistentStoreCoordinator {

  @objc func x_migratePersistentStore(_ store: NSPersistentStore, to URL: URL, options: [AnyHashable : Any]? = nil, withType storeType: String) throws -> NSPersistentStore {
    var opt: [AnyHashable : Any] = options ?? [:]

    if #available(OSX 10.13, *) {
      opt[NSBinaryStoreSecureDecodingClasses] = NSSet(array: [ NSColor.self ])
    }

    return try x_migratePersistentStore(store, to: URL, options: opt, withType: storeType)
  }

  class MigratePersistentStoreInitializer {
    init() {
      let s1 = #selector(NSPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:))
      let s2 = #selector(NSPersistentStoreCoordinator.x_migratePersistentStore(_:to:options:withType:))
      let m1 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s1)!
      let m2 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s2)!
      method_exchangeImplementations(m1, m2)
    }

    static let singlton = MigratePersistentStoreInitializer()  // Lazy Stored Property
  }

}

class Document: NSPersistentDocument {

  override init() {
    super.init()
    let _ = NSPersistentStoreCoordinator.MigratePersistentStoreInitializer.singlton
  }

  override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {
    // keep yours
  }

}

参考:

  • Lazy Stored Properties

这篇关于未为saveAs NSPersistentDocument调用configurePersistentStoreCoordinator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆