NSCoder "only defined abstract class" 问题

NSCoder "only defined abstract class" woes

我有一个简单的 class,它(一旦充实)将构成由 NSDocument subclass 处理的数据。但是,我在尝试使用 NSDocument 的 data(ofType:) 和 read(from: ofType:) 方法 save/init class 时遇到了困难。

我在调试器中看到的错误是:

[General] *** -encodeObject:forKey: only defined for abstract class. Define -[NSArchiver encodeObject:forKey:]!

我的 NSDocument 子文档class 看起来像:

class Document: NSDocument
{
  private(set) var coverTree = CoverTree()

  // ... skipping boilerplate init and makeWindowControllers methods

  override class func autosavesInPlace() -> Bool {
    return false
  }

  override func data(ofType typeName: String) throws -> Data
  {
    return NSArchiver.archivedData(withRootObject: coverTree)
  }

  override func read(from data: Data, ofType typeName: String) throws
  {        
    if let ct = NSUnarchiver(forReadingWith: data)?.decodeObject() as? CoverTree
    {
      coverTree = ct
    }
  }
}

我的 CoverTree class 目前看起来像:

import Cocoa

class CoverTree: NSObject, NSCoding
{
  private(set) var generated = false

  let creationStamp : String

  override init()
  {
    let df = DateFormatter()
    df.dateStyle = .full
    df.timeStyle = .full

    creationStamp = df.string(from: Date())

    super.init()
  }

  required init(coder decoder:NSCoder)
  {
    creationStamp = decoder.decodeObject(forKey: "creation") as! String
  }

  func encode(with coder: NSCoder)
  {
    coder.encode(self.creationStamp, forKey:"creation")
  }

  func generate( dataSet : DataSet) -> Void
  {
    generated = true
  }
}

执行CoverTree::encode()

中唯一一行时出现错误

我一直在竭尽全力寻找 Whosebug 内外的示例。我所拥有的似乎遵循所有建议 patterns/snippets。

对错误字符串的搜索表明错误是由于使用 NSCoder 而不是 NSKeyedArchiver...。但是如果我将编码的签名更改为编码(使用 coder:NSKeyedArchiver),我会得到一个错误CoverTree 不符合 NSCoding。

我错过了什么?

非常感谢, 麦克

如果对您有帮助,这里是完整的堆栈跟踪:

2017-09-11 09:55:44.682537-0400 coverTreeDemo[40650:3798144] [General] *** -encodeObject:forKey: only defined for abstract class.  Define -[NSArchiver encodeObject:forKey:]!
2017-09-11 09:55:44.691417-0400 coverTreeDemo[40650:3798144] [General] (
    0   CoreFoundation                      0x00007fffa3ae357b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x00007fffb8d3c1da objc_exception_throw + 48
    2   CoreFoundation                      0x00007fffa3b60c55 +[NSException raise:format:] + 197
    3   Foundation                          0x00007fffa5621abe NSRequestConcreteImplementation + 229
    4   coverTreeDemo                       0x0000000100003583 _TFC13coverTreeDemo9CoverTree6encodefT4withCSo7NSCoder_T_ + 163
    5   coverTreeDemo                       0x00000001000035fa _TToFC13coverTreeDemo9CoverTree6encodefT4withCSo7NSCoder_T_ + 58
    6   Foundation                          0x00007fffa54922e1 -[NSArchiver encodeRootObject:] + 164
    7   Foundation                          0x00007fffa5491a66 +[NSArchiver archivedDataWithRootObject:] + 141
    8   coverTreeDemo                       0x0000000100003f3b _TFC13coverTreeDemo8Document4datafzT6ofTypeSS_V10Foundation4Data + 491
    9   coverTreeDemo                       0x000000010000402b _TToFC13coverTreeDemo8Document4datafzT6ofTypeSS_V10Foundation4Data + 91
    10  AppKit                              0x00007fffa190121c -[NSDocument writeToURL:ofType:error:] + 812
    11  AppKit                              0x00007fffa1900ead -[NSDocument writeToURL:ofType:forSaveOperation:originalContentsURL:error:] + 445
    12  AppKit                              0x00007fffa208bbb1 -[NSDocument(NSDocumentSaving) _writeSafelyToURL:ofType:forSaveOperation:forceTemporaryDirectory:error:] + 915
    13  AppKit                              0x00007fffa208c8b7 -[NSDocument(NSDocumentSaving) _writeSafelyToURL:ofType:forSaveOperation:error:] + 28
    14  AppKit                              0x00007fffa190089e -[NSDocument writeSafelyToURL:ofType:forSaveOperation:error:] + 355
    15  AppKit                              0x00007fffa20978c5 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_2.1116 + 233
    16  AppKit                              0x00007fffa20977cd __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke.1113 + 454
    17  AppKit                              0x00007fffa2095903 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke_2.969 + 2071
    18  Foundation                          0x00007fffa56e8e48 __85-[NSFileCoordinator(NSPrivate) _coordinateWritingItemAtURL:options:error:byAccessor:]_block_invoke.404 + 226
    19  Foundation                          0x00007fffa56e88ab -[NSFileCoordinator(NSPrivate) _withAccessArbiter:invokeAccessor:orDont:andRelinquishAccessClaim:] + 493
    20  Foundation                          0x00007fffa557e206 -[NSFileCoordinator(NSPrivate) _coordinateWritingItemAtURL:options:error:byAccessor:] + 862
    21  AppKit                              0x00007fffa2092dd0 -[NSDocument(NSDocumentSaving) _fileCoordinator:coordinateReadingContentsAndWritingItemAtURL:byAccessor:] + 387
    22  AppKit                              0x00007fffa20950d4 __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke.964 + 544
    23  AppKit                              0x00007fffa209462b __85-[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:]_block_invoke + 508
    24  AppKit                              0x00007fffa1b2abd6 -[NSDocument(NSDocumentSerializationAPIs) continueFileAccessUsingBlock:] + 222
    25  AppKit                              0x00007fffa1b2b477 -[NSDocument(NSDocumentSerializationAPIs) _performFileAccess:] + 782
    26  AppKit                              0x00007fffa2094429 -[NSDocument(NSDocumentSaving) _saveToURL:ofType:forSaveOperation:completionHandler:] + 92
    27  AppKit                              0x00007fffa194b2a8 __85-[NSDocument saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:]_block_invoke_2 + 256
    28  AppKit                              0x00007fffa18ba1e2 -[NSDocument _commitEditingThenContinue:] + 474
    29  AppKit                              0x00007fffa18b9fff -[NSDocument _commitEditingWithDelegate:didSomethingSelector:contextInfo:thenContinue:] + 92
    30  AppKit                              0x00007fffa194b196 __85-[NSDocument saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:]_block_invoke + 444
    31  AppKit                              0x00007fffa1b2a305 -[NSDocument(NSDocumentSerializationAPIs) performActivityWithSynchronousWaiting:usingBlock:cancellationHandler:] + 475
    32  AppKit                              0x00007fffa194afd4 -[NSDocument saveToURL:ofType:forSaveOperation:delegate:didSaveSelector:contextInfo:] + 113
    33  AppKit                              0x00007fffa2090ff1 __104-[NSDocument(NSDocumentSaving) _runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo:]_block_invoke.595 + 113
    34  AppKit                              0x00007fffa1b2a4d3 -[NSDocument(NSDocumentSerializationAPIs) _continueActivityUsingBlock:] + 320
    35  AppKit                              0x00007fffa2090de5 __104-[NSDocument(NSDocumentSaving) _runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo:]_block_invoke_2.580 + 506
    36  AppKit                              0x00007fffa209097c __104-[NSDocument(NSDocumentSaving) _runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo:]_block_invoke.561 + 1500
    37  AppKit                              0x00007fffa1c558b9 -[NSSavePanel _didEndSheet:returnCode:contextInfo:] + 95
    38  AppKit                              0x00007fffa17c3b84 -[NSWindow _endWindowBlockingModalSession:returnCode:] + 308
    39  AppKit                              0x00007fffa1c581c6 -[NSSavePanel overwriteAlertDidEnd:returnCode:contextInfo:] + 256
    40  AppKit                              0x00007fffa197a1e3 -[NSAlert didEndAlert:returnCode:contextInfo:] + 90
    41  AppKit                              0x00007fffa17c3b84 -[NSWindow _endWindowBlockingModalSession:returnCode:] + 308
    42  AppKit                              0x00007fffa18239e3 -[NSAlert buttonPressed:] + 107
    43  libsystem_trace.dylib               0x00007fffb984f3a7 _os_activity_initiate_impl + 53
    44  AppKit                              0x00007fffa1cd0721 -[NSApplication(NSResponder) sendAction:to:from:] + 456
    45  AppKit                              0x00007fffa17b4cc4 -[NSControl sendAction:to:] + 86
    46  AppKit                              0x00007fffa17b4bec __26-[NSCell _sendActionFrom:]_block_invoke + 136
    47  libsystem_trace.dylib               0x00007fffb984f3a7 _os_activity_initiate_impl + 53
    48  AppKit                              0x00007fffa17b4b44 -[NSCell _sendActionFrom:] + 128
    49  AppKit                              0x00007fffa17f7539 -[NSButtonCell _sendActionFrom:] + 98
    50  libsystem_trace.dylib               0x00007fffb984f3a7 _os_activity_initiate_impl + 53
    51  AppKit                              0x00007fffa17b3426 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2481
    52  AppKit                              0x00007fffa17f7272 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 798
    53  AppKit                              0x00007fffa17b1ddb -[NSControl mouseDown:] + 832
    54  AppKit                              0x00007fffa1e4c24f -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 6341
    55  AppKit                              0x00007fffa1e48a6c -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 1942
    56  AppKit                              0x00007fffa1e47f0a -[NSWindow(NSEventRouting) sendEvent:] + 541
    57  AppKit                              0x00007fffa1ccc681 -[NSApplication(NSEvent) sendEvent:] + 1145
    58  AppKit                              0x00007fffa1547427 -[NSApplication run] + 1002
    59  AppKit                              0x00007fffa1511e0e NSApplicationMain + 1237
    60  coverTreeDemo                       0x0000000100002cbd main + 13
    61  libdyld.dylib                       0x00007fffb961d235 start + 1
)

问题是您在 NSDocument 子类中引用了 NSArchiver 和 NSUnarchiver。那是错误的。这些 类 已弃用。您应该使用 NSKeyedArchiver 和 NSKeyedUnarchiver 来替代它们。 docs 对此很清楚:

In macOS 10.2 and later, NSArchiver and NSUnarchiver have been replaced by NSKeyedArchiver and NSKeyedUnarchiver respectively