NSKeyedArchiver归档数据时崩溃
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NSKeyedArchiver归档数据时崩溃相关的知识,希望对你有一定的参考价值。
我的应用程序使用以下函数来序列化一组自定义对象(仅显示相关代码):
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
不是线程安全的吗?
我怀疑的问题确实是由多个线程的非同步访问引起的:
一个NSArchiver
遍历一个对象图,从根对象开始,并在它遇到的每个对象的路上存档。
因此,为了创建正确的存档,需要在存档器终止之前不改变对象图。
在单线程应用程序中,这是自动保证的。 在一个多线程应用程序中,多个线程可以改变对象图,程序员负责确保这一点,因为归档程序无法阻止其他线程改变根对象。 (例如,如果归档器首先制作对象图的深层副本,然后归档副本,则在深拷贝期间可以突变对象图)。
因此,需要序列化对象图的所有获取和设置访问,例如,通过在串行访问队列中执行它们。
以上是关于NSKeyedArchiver归档数据时崩溃的主要内容,如果未能解决你的问题,请参考以下文章