【问题标题】:Crash while archiving data by NSKeyedArchiverNSKeyedArchiver 归档数据时崩溃
【发布时间】: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


【解决方案1】:

我的问题确实是由多个线程的不同步访问引起的:

NSArchiver 遍历对象图,从根对象开始,并沿遇到的每个对象归档。
为了创建正确的存档,因此要求对象图在存档程序终止之前不发生变化。

在单线程应用程序中,这是自动保证的。
在多线程应用程序中,超过 1 个线程可以改变对象图,程序员有责任确保这一点,因为归档器无法阻止其他线程改变根对象。 (例如,如果存档器首先制作对象图的深层副本,然后存档副本,则对象图可能会在深层复制期间发生变异)。

因此需要对对象图的所有 get 和 set 访问进行序列化,例如通过在串行访问队列中执行它们。

【讨论】:

  • let archivedObject = NSKeyedArchiver.archivedData(withRootObject: recentCalls as NSArray) let defaults = UserDefaults.standard defaults.set(archivedObject, forKey: recentCalls) defaults.synchronize() 我用这些来保存我的模型数组的 UserDefaults 中的数据,但由于内存问题,此时应用程序仅在 iPhone 7 上崩溃。此归档过程需要大约 800 MB 或更多内存并崩溃。您能否为此提供任何解决方案以防止内存问题和崩溃??? @Reinhard 方式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 2011-04-12
  • 1970-01-01
  • 1970-01-01
  • 2018-10-01
  • 1970-01-01
相关资源
最近更新 更多