我遇到了一个关于保存NSPersistentDocument的奇怪行为。我可以创建一个没有问题的自动保存的新文档。但是当我保存它时write(to: ofType: for: absoluteOriginalContentsURL:)
被调用但转向configurePersistentStoreCoordinator(for: ofType: modelConfiguration: storeOptions:)
未被调用。这很不幸,因为我需要配置商店。原因是我需要将NSColor注册为可解码的options[NSBinaryStoreSecureDecodingClasses] = NSSet(object: NSColor.self)
。
第一次尝试是自己打电话,但这并没有把我带到任何地方。自己调用它没有按预期注册设置。
我的NSPersistentDocument中的代码如下所示:
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)")
}
}
结果是以下输出(第二个configurePersistentStoreCoordinator输出在通过菜单命令保存后启动):
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的问题!这是一个相关的堆栈跟踪。它不是来自同一个会话,而是导致相同的结果。
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的解决方案(通过方法调配)工作正常。但是,有时(不确定何时)会导致同样的问题。这是更新的堆栈跟踪。这很神秘。 : - )
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
答案 0 :(得分:1)
谢谢Kneup的@Wizard!
这清楚地表明应用程序肯定会读取文档文件然后遇到错误。
让我们开始调查。
(1)该应用尝试读取哪个文件?
(lldb) breakpoint set -n '-[NSBinaryObjectStoreFile readFromFile:error:]'
Breakpoint 3: # locations.
再次运行应用程序以重现问题。断点命中后,在lldb提示符下键入以下命令:
po $rdi
p (SEL)$rsi
po $rdx
po $rcx
po $r8
po $r9
将显示文件名。禁用断点。使用之前设置的断点处返回的数字#。例如3
(lldb) breakpoint disable 3
(2)该应用尝试解码的对象是什么?
(lldb) breakpoint set -n '-[NSKeyedUnarchiver _decodeArrayOfObjectsForKey:]'
Breakpoint 4: # locations.
与上述相同。使用一组po
命令获取一些信息。这似乎是一堆东西。
(lldb) breakpoint disable 4
(3)应用程序拒绝解码哪个类?
(lldb) breakpoint set -n '-[NSCoder _validateAllowedClass:forKey:allowingInvocations:]'
我逐个编写了断点并且每次都禁用。但是,没有必要这样做。或者,一次设置所有断点,然后点击并调查然后继续。
问题是应用程序读取文件的原因。那可能是移民。
-[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:]
但是为什么不调用override func configurePersistentStoreCoordinator()
?我现在对此一无所知。
我希望您能有一些提示,以便更接近解决方案。
已添加:
要设置断点,有时我们需要在执行应用程序的最开始时停止。
例如,在init()
AppDelegate
设置一个断点,以便有机会手动设置断点。
class AppDelegate: NSObject, NSApplicationDelegate {
override init() {
=> super.init()
}
}
<强>追加:强>
我误解了。纠正:
当使用所需的URL(即文件名)实例化类func configurePersistentStoreCoordinator
时,似乎会调用NSPersistentStore
。因此,时间与读取或写入文档文件的操作无关。相反,这是第一次将内部文档连接到URL。
func configurePersistentStoreCoordinator
。我们已经看到,如果文档已经提前从现有文件加载,那么在SaveAs上调用func configurePersistentStoreCoordinator
似乎是正常的。我认为,我们在那个函数中提供的NSPersistentStore
的选项已经存在。
设置断点的提示
答案 1 :(得分:1)
好消息和坏消息
我已成功在MacOS 10.13.2上运行Xcode 9.2重现完全相同的错误。
NSBinaryStoreSecureDecodingClasses
选项读取Autosave目录中版本1的文件。NSPersistentStoreCoordinator .migratePersistentStore()
又名-[NSPersistentStoreCoordinator migratePersistentStore:toURL:options:withType:error:]:
migratePersistentStore
的过程中,NSBinaryStoreSecureDecodingClasses
选项未设置为写入和读取临时文件。 对我来说有点奇怪。为什么在保存时执行迁移,而不是在打开文件时执行?在步骤3中已经完成了轻量级迁移?
修改强>
似乎migratePersistentStore
的名称并不意味着从旧版本迁移到新版本。这似乎意味着从具有旧URL(即文件名和/或文件格式)的旧持久性存储迁移到具有新URL和/或文件格式的新持久性存储。因此,当另存为...或保存已保存在自动保存目录中的新文档时,将调用它。
答案 2 :(得分:1)
你能试试这个讨厌的解决方法吗?
class CustomPersistentStoreCoordinator : NSPersistentStoreCoordinator {
static var m1 : Method? = nil
static var m2 : Method? = nil
override func 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 ])
}
let m1 = CustomPersistentStoreCoordinator.m1!
let m2 = CustomPersistentStoreCoordinator.m2!
method_exchangeImplementations(m2, m1)
let x = try self.migratePersistentStore(store, to: URL, options: opt, withType: storeType)
method_exchangeImplementations(m1, m2)
return x
}
}
class Document: NSPersistentDocument {
override init() {
super.init()
let s1 = #selector(NSPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:))
let s2 = #selector(CustomPersistentStoreCoordinator.migratePersistentStore(_:to:options:withType:))
let m1 = class_getInstanceMethod(NSPersistentStoreCoordinator.self, s1)!
let m2 = class_getInstanceMethod(CustomPersistentStoreCoordinator.self, s2)!
CustomPersistentStoreCoordinator.m1 = m1
CustomPersistentStoreCoordinator.m2 = m2
method_exchangeImplementations(m1, m2)
}
override func configurePersistentStoreCoordinator(for url: URL, ofType fileType: String, modelConfiguration configuration: String?, storeOptions: [String : Any]? = nil) throws {
// keep yours
}
}
答案 3 :(得分:1)
另一种更简单的解决方法:
以下代码有错误。请参阅下面引用的错误修复版本。
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
。
错误修正版
前面的解决方法中存在错误。打开文档文件,创建新文件,进行更改,等待30秒自动保存的文档,关闭它们和/或随机保存它们将导致初始错误。由Kneup向导报道。
这是一个使用singleton的固定版本,以确保只应用一次swizzling。
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
}
}
参考文献: