【发布时间】:2017-12-24 11:52:56
【问题描述】:
我的应用程序使用以下函数序列化一组自定义对象(仅显示相关代码):
class func serializeShoppingLocations(buyLocations: Set<ShoppingLocation>) -> Data {
#if os(iOS)
NSKeyedArchiver.setClassName("ShoppingLocation", for: ShoppingListIOS.ShoppingLocation.self)
#elseif os(watchOS)
NSKeyedArchiver.setClassName("ShoppingLocation", for: ShoppingListWatch.ShoppingLocation.self)
#endif
let data = NSKeyedArchiver.archivedData(withRootObject: buyLocations)
return data
}
需要对 iOS 和 watchOS 目标进行条件编译,以允许这两个目标稍后解除序列化数据,即使它们已被另一个目标存档。
ShoppingLocation采用NSCoding协议,继承自NSObject。
此代码在 let data = … 指令处崩溃,并带有 EXC_BAD_ACCESS (code=1, address=0x0)。
我知道该错误可能表明引用了一个不存在的对象。但是,变量buyLocations是存在的,我可以在调试器中打印出值,包括集合中对象的所有值。
堆栈跟踪表明归档器开始归档NSSet,并尝试归档集合中的一个元素,但内部可变字典中的setObjectForKey 失败。
可能是什么原因?
编辑:
在进一步的测试中,我意识到崩溃总是在应用程序的至少 2 个线程处于活动状态时发生。
特别是,我发现了一种情况,其中一个线程在与上述不同的指令处崩溃(Xcode 中的红色):
let dataBlob = NSKeyedArchiver.archivedData(withRootObject: shoppingItem.buyLocations)
而另一个线程在上述指令处停止(Xcode 中为绿色):
let data = NSKeyedArchiver.archivedData(withRootObject: buyLocations)
可能是NSKeyedArchiver 不是线程安全的?
【问题讨论】:
-
确保 ShoppingLocation 继承自 NSObject
-
@Leo Dabus 感谢您的提示,但 ShoppingLocation 继承自 NSObject。我会更新我的问题。
标签: ios swift thread-safety nskeyedarchiver