添加了一个自定义框架,现在 Swift 无法取消归档数据

Posted

技术标签:

【中文标题】添加了一个自定义框架,现在 Swift 无法取消归档数据【英文标题】:Added a custom framework, now Swift can't unarchive data 【发布时间】:2015-04-18 14:51:35 【问题描述】:

我有一个非常简单的 Swift 应用程序,它有一个名为 DemoNote 的模型类。一组DemoNote 实例通过密钥归档读取/写入。当 DemoNote 包含在应用程序中时,这工作正常。

但后来我将DemoNote.swift 移到了一个名为DemoSharedCode 的新自定义框架中。除了确保 Xcode 在应用程序目标中使用框架之外,我还确保

DemoNote 及其变量和方法标记为public,以便它们在框架外可见 将import DemoSharedCode 添加到任何想要使用DemoNote 的类

所以现在编译器很高兴。但在运行时,解压失败并出现以下错误:

2015-02-17 12:12:53.417 DemoNotesSwift[70800:16504104] *** Terminating app due to 
uncaught exception 'NSInvalidUnarchiveOperationException', reason:
'*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class
(DemoNotesSwift.DemoNote)'

在上面,DemoNotesSwift 是应用名称,DemoNote 是类名称,代码行试图从 NSData blob 中解压缩对象:

let savedObjects = NSKeyedUnarchiver.unarchiveObjectWithData(savedData) as? [(DemoNote)]

我猜测将DemoNote 移动到框架意味着它的模块名称已更改,这会破坏取消归档,但我不确定。我也不知道该怎么办——也许我需要在 unarchiver 上调用 +setClass:forClassName:,但如果是这样,我不知道参数会是什么。

【问题讨论】:

归档器在内部做的事情有点模糊。有一个开源项目可以帮助阅读档案(我放弃了,太噩梦了)。但它可能会存储一些类签名。因此,如果您在引擎盖下更改它(这绝不是一个好主意),它会(在您的情况下很可能)会发牢骚。只是一个想法,不是基于实践经验。 我之前在 Objective-C 中做过同样的事情(从字面上看,就像我在用不同的语言做同样的演示项目一样)并且没问题。必须可以在 Swift 中做同样的事情。 我明白了。所以我猜 Swift 框架现在不同了。尽管两种语言之间有一些免费的桥接,但它似乎在这里不起作用。您可能只能尝试错误:-/我猜您已经在 Google 上搜索了 NSInvalidUnarchiveOperationException 并找到了 SO 答案。 【参考方案1】:

DemoNote 从应用程序移动到框架确实更改了模块名称,这意味着NSKeyedUnarchiver 由于名称不匹配而无法找到归档类的实例。解决方法是在取消归档之前添加这一行:

NSKeyedUnarchiver.setClass(DemoNote.self, forClassName: "DemoNotesSwift.DemoNote")

在这种情况下,DemoNote.self 获取当前的完整类名,DemoNotesSwift.DemoNote 是该类在成为应用程序的一部分时曾经被调用的名称。

这只是必要的,因为我想保留以前存在的数据。

【讨论】:

在哪里可以找到有关创建 100% Swift 框架的教程? -- 我是一个框架新手,刚刚掌握了 Swift 的 ObjC 框架。但我不知道如何在没有标题的 Swift 中收集“标题”/ObjC。 您是否也知道如何让 nskeyedarchiver 在下次存储类时以正确的名称存档它? 一般都不是问题,我只是因为我的重构出了问题。如果你真的需要它,NSKeyedArchiver 有一个与我使用的方法相反的方法——setClassName(_: forClass:) 虽然我不知道细节,你也可以使用NSKeyedUnarchiver.setClass(DemoNote.classForKeyedUnarchiver(), forClassName: "DemoNotesSwift.DemoNote")classForKeyedUnarchiver()的方法看起来更合适。 如果您想覆盖默认类,则该方法似乎适用于 - 也就是说,特别是如果您不想想要使用 ClassName.self 但想要一些其他类。它在某些情况下很有用,但我认为在这种情况下不太合适。

以上是关于添加了一个自定义框架,现在 Swift 无法取消归档数据的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 Swift 框架中的 Objective-C 文件上使用 Swift

使用 Swift (iOS) 和 Photos 框架保存自定义图像的元数据

框架中的自定义 ui 组件未呈现到故事板

自定义按钮无法点击 Swift

Swift 3:如何在使用 AVFoundation 录制视频期间将麦克风静音/取消静音

如何在 Swift 中归档和取消归档自定义对象?或者如何在 Swift 中将自定义对象保存到 NSUserDefaults?