如何在 iOS 12 中替换 NSKeyedArchiver 的初始化程序 init(forWritingWith:) 以编码 CKRecord 的元数据
How to replace NSKeyedArchiver's initializer init(forWritingWith:) in iOS 12 to encode the metadata of a CKRecord
在 iOS 12 中,NSKeyedArchiver 的初始化程序 init(forWritingWith:) 已被弃用。 Xcode 10 建议用新的初始化程序 init(requiringSecureCoding:) 替换它。问题是这个初始化器只设置了 NSCoder 对象的 requiresSecureCoding 属性 的值,但它没有设置将包含编码数据的 NSMutableData 对象。以下是 Apple 提出的对 CKRecord(CloudKit 记录)的元数据进行编码的原始代码:
let data = NSMutableData()
let coder = NSKeyedArchiver.init(forWritingWith: data)
coder.requiresSecureCoding = true
record.encodeSystemFields(with: coder)
coder.finishEncoding()
CKRecord class 的 encodeSystemFields 方法需要一个 NSKeyedArchiver 对象(一个 NSCoder 子class),编码后的数据存储在与该对象关联的 NSMutableData 对象中。如果我用 init(requiringSecureCoding:) 初始化器替换 init(forWritingWith:) 初始化器,我得到一个 NSKeyedArchiver 对象,但是这个对象不与任何 NSMutableData 对象关联,因此我没有得到记录的元数据。我不确定如何完成代码以将 NSKeyedArchiver 对象生成的数据放入 NSMutableData 对象中。
对于现在的一些版本,NSKeyedArchiver
有一个 encodedData
method,它在归档器上调用 -finishEncoding
,并向您 returns 归档器创建的最终编码数据.这就是通过 -[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
以便仅对自身的一个子集进行编码。在对对象进行编码的一般情况下,您会使用 the new NSKeyedArchiver.archivedData(withRootObject:requiringSecureCoding:)
method:
let data = try NSKeyedArchiver.archivedData(withRootObject: /* object */, requiringSecureCoding: true)
相当于
let coder = NSKeyedArchiver(requiringSecureCoding: true)
coder.encodeObject(/* object */, forKey: NSKeyedArchiveRootObjectKey)
let data = coder.encodedData
在 iOS 12 中,NSKeyedArchiver 的初始化程序 init(forWritingWith:) 已被弃用。 Xcode 10 建议用新的初始化程序 init(requiringSecureCoding:) 替换它。问题是这个初始化器只设置了 NSCoder 对象的 requiresSecureCoding 属性 的值,但它没有设置将包含编码数据的 NSMutableData 对象。以下是 Apple 提出的对 CKRecord(CloudKit 记录)的元数据进行编码的原始代码:
let data = NSMutableData()
let coder = NSKeyedArchiver.init(forWritingWith: data)
coder.requiresSecureCoding = true
record.encodeSystemFields(with: coder)
coder.finishEncoding()
CKRecord class 的 encodeSystemFields 方法需要一个 NSKeyedArchiver 对象(一个 NSCoder 子class),编码后的数据存储在与该对象关联的 NSMutableData 对象中。如果我用 init(requiringSecureCoding:) 初始化器替换 init(forWritingWith:) 初始化器,我得到一个 NSKeyedArchiver 对象,但是这个对象不与任何 NSMutableData 对象关联,因此我没有得到记录的元数据。我不确定如何完成代码以将 NSKeyedArchiver 对象生成的数据放入 NSMutableData 对象中。
对于现在的一些版本,NSKeyedArchiver
有一个 encodedData
method,它在归档器上调用 -finishEncoding
,并向您 returns 归档器创建的最终编码数据.这就是通过 -[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
以便仅对自身的一个子集进行编码。在对对象进行编码的一般情况下,您会使用 the new NSKeyedArchiver.archivedData(withRootObject:requiringSecureCoding:)
method:
let data = try NSKeyedArchiver.archivedData(withRootObject: /* object */, requiringSecureCoding: true)
相当于
let coder = NSKeyedArchiver(requiringSecureCoding: true)
coder.encodeObject(/* object */, forKey: NSKeyedArchiveRootObjectKey)
let data = coder.encodedData