在iOS 12中,不推荐使用NSKeyedArchiver的初始化程序init(forWritingWith :)。 Xcode 10建议将其替换为新的初始化程序init(requireringSecureCoding :)。问题在于此初始化程序仅设置NSCoder对象的requireSecureCoding属性的值,但没有设置将包含编码数据的NSMutableData对象。以下是Apple提出的用于编码CKRecord(CloudKit记录)的元数据的原始代码:
let data = NSMutableData()
let coder = NSKeyedArchiver.init(forWritingWith: data)
coder.requiresSecureCoding = true
record.encodeSystemFields(with: coder)
coder.finishEncoding()
CKRecord类的encodeSystemFields方法需要一个NSKeyedArchiver对象(一个NSCoder子类),并且已编码的数据存储在与此对象关联的NSMutableData对象中。如果我用init(requiringSecureCoding :)初始值设定项替换init(forWritingWith :)初始值设定项,则会得到一个NSKeyedArchiver对象,但该对象与任何NSMutableData对象均不相关,因此不会获得记录的元数据。我不确定如何完成代码以将NSKeyedArchiver对象产生的数据转换为NSMutableData对象。
答案 0 :(得分:9)
对于某些发行版,NSKeyedArchiver
拥有一个encodedData
method,该the new NSKeyedArchiver.archivedData(withRootObject:requiringSecureCoding:)
method在存档器上调用-finishEncoding
,并向您返回存档器创建的最终编码数据。这就是通过-[NSKeyedArchiver init]
进行初始化时如何获取完成的数据:
let coder = NSKeyedArchiver()
/* encode stuff */
let data = coder.encodedData
这消除了对NSMutableData
变体的需求,并且在此更新中,不推荐使用可变数据变体,从而支持较新的范例。所以不要写
let data = NSMutableData()
let coder = NSKeyedArchiver.init(forWritingWith: data)
coder.requiresSecureCoding = true
record.encodeSystemFields(with: coder)
coder.finishEncoding()
你会写
let coder = NSKeyedArchiver(requiringSecureCoding: true)
record.encodeSystemFields(with: coder)
let data = coder.encodedData
手动分配给.requiresSecureCoding
和手动finishEncoding()
都不再需要。
请注意,只有在调用CKRecord.encodeSystemFields(with:)
时才需要执行此舞蹈,该调用显式地使用NSCoder
以便仅编码其自身的子集。在编码对象的一般情况下,您可以使用https://github.com/rferrazz/pyqt4topyqt5:
let data = try NSKeyedArchiver.archivedData(withRootObject: /* object */, requiringSecureCoding: true)
等效于
let coder = NSKeyedArchiver(requiringSecureCoding: true)
coder.encodeObject(/* object */, forKey: NSKeyedArchiveRootObjectKey)
let data = coder.encodedData