如何在iOS 12中替换NSKeyedArchiver的初始值设定项init(forWritingWith :)对CKRecord的元数据进行编码

时间:2018-07-17 02:50:51

标签: nskeyedarchiver nscoder

在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对象。

1 个答案:

答案 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