【问题标题】:NSCoder "only defined abstract class" woesNSCoder“只定义抽象类”的困境
【发布时间】:2017-09-11 14:13:32
【问题描述】:

我有一个简单的类(一旦充实)将构成由 NSDocument 子类处理的数据。但是,我在尝试使用 NSDocument 的 data(ofType:) 和 read(from: ofType:) 方法保存/初始化类时被卡住了。

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

[General] *** -encodeObject:forKey: 只为抽象类定义。 定义-[NSArchiver encodeObject:forKey:]!

我的 NSDocument 的 Document 子类如下所示:

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 类目前看起来像:

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()中唯一一行时出现错误

我一直在寻找 StackOverflow 内外的示例。我所拥有的似乎遵循所有建议的模式/sn-ps。

对错误字符串的搜索表明该错误是由于使用 NSCoder 而不是 NSKeyedArchiver....但是如果我将 encode 的签名更改为 encode(with 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
)

【问题讨论】:

  • 这是我查看的众多问题/答案之一,但它并没有帮助我解决问题。现在知道核心问题是使用无密钥版本的存档器,我可以看到这个信息在 3892578 中......但是当我不知道问题到底是什么时,解决方案并不明显。

标签: swift cocoa nsdocument nscoder


【解决方案1】:

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

在 macOS 10.2 及更高版本中,NSArchiver 和 NS归档器 已被替换 NSKeyedArchiver 和 NSKeyedUnarchiver 分别

【讨论】:

  • 具体来说,问题是@MikeMayer67 在NSArchiverNSUnarchiver 上使用密钥归档方法(虽然通过NSCoder 超类公开,但明确未实现)。 [只需将NSArchiver 替换为NSKeyedArchiver 并将NSUnarchiver 替换为NSKeyedUnarchiver 就足以解决此问题。]
  • 一如既往地感谢@ItaiFerber
  • 这实际上是我开始的,但我还有其他问题......所以我切换到无键版本,看看是否能解决我的问题。然后当事情仍然无法正常工作时忘记将其切换回来。即使我将它们切换回键控版本,上面的代码示例仍然存在问题(这是一个不同的问题)。在寻求其他帮助之前,我会看看我是否能彻底解决问题。
猜你喜欢
  • 2016-07-31
  • 1970-01-01
  • 1970-01-01
  • 2020-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-26
相关资源
最近更新 更多