格式错误的 NSKeyedUnarchiver 数据
NSKeyedUnarchiver data in wrong format
我正在使用 ARKit 和 GameKitMatches,所以我不能使用 Codable (afaik),因为 MCPeerID
和 ARWorldMap
都不可编码,首先要解决这个问题。
所以我正在使用 NSCoding 和 NSSecureCoding,但出于某种原因我总是会遇到错误:
The data couldn’t be read because it isn’t in the correct format.
...即使是我刚刚创建的。
我也尝试使用 NSKeyedUnarchiver.unarchivedObject(ofClasses: classes
但在我的 init.
中抛出了一个 unexpected-nil
这是我制作的展示问题的游乐场:
class CodingData: NSObject, NSCoding, NSSecureCoding {
static var supportsSecureCoding = true
var dic: [String: Int]!
var i: Int!
func encode(with coder: NSCoder) {
coder.encode(i, forKey: "i")
coder.encode(dic, forKey: "dic")
}
required convenience init?(coder: NSCoder) {
let anInt = coder.decodeObject(forKey: "i") as! Int
let anDic = coder.decodeObject(forKey: "dic") as! [String: Int]
self.init(dic: anDic, i: anInt)
}
init(dic: [String: Int], i: Int){
self.dic = dic
self.i = i
}
}
do{
let test = CodingData(dic: [:], i: 0)
//let classes = [NSDictionary.self, NSNumber.self]
let testData = try NSKeyedArchiver.archivedData(withRootObject: test, requiringSecureCoding: true)
let emptyDic = try NSKeyedUnarchiver.unarchivedObject(ofClass: CodingData.self, from: testData)
// Error here ^^^^^^
}catch{
error.localizedDescription
}
顺便说一句,不确定它是否重要但是在尝试调试 init 中的 coder
时它总是说(可能只是一个错误):
error: <EXPR>:1:1: error: non-nominal type '$__lldb_context' (aka 'Self') cannot be extended
extension $__lldb_context {
^ ~~~~~~~~~~~~~~~
error: <EXPR>:19:27: error: value of type 'Self' has no member '$__lldb_wrapped_expr_28'
$__lldb_injected_self.$__lldb_wrapped_expr_28(
~~~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~
您已经很努力了,但是您的代码有很多错误,我认为最简单的回答方法就是更正它:
class CodingData: NSObject, NSSecureCoding {
static var supportsSecureCoding = true
var dic: [String: Int]
var i: Int
func encode(with coder: NSCoder) {
coder.encode(i as NSNumber, forKey: "i")
coder.encode(dic as NSDictionary, forKey: "dic")
}
required init?(coder: NSCoder) {
let anInt = coder.decodeObject(of: NSNumber.self, forKey: "i")
let anDic = coder.decodeObject(of: NSDictionary.self, forKey: "dic")
self.dic = anDic as! [String:Int]
self.i = anInt as! Int
}
init(dic: [String: Int], i: Int){
self.dic = dic
self.i = i
}
}
现在可以使用了:
let test = CodingData(dic: [:], i: 0)
let testData = try NSKeyedArchiver.archivedData(withRootObject: test, requiringSecureCoding: true)
let emptyDic = try NSKeyedUnarchiver.unarchivedObject(ofClass: CodingData.self, from: testData)
print(emptyDic?.dic as Any, emptyDic?.i as Any) // Optional([:]) Optional(0)
所以你的四个主要错误是:
不要将实例 属性 声明为隐式展开的可选 (!
)
init?(coder:)
不是 convenience
初始值设定项
要进行安全编码,您必须使用安全编码 (decodeObject(of:forKey:)
)
对每个编码的 属性 进行解码
只有 NSSecureCoding 类型可以使用安全编码进行编码,因此 Swift 类型必须转换为其 Objective-C 等价物
我正在使用 ARKit 和 GameKitMatches,所以我不能使用 Codable (afaik),因为 MCPeerID
和 ARWorldMap
都不可编码,首先要解决这个问题。
所以我正在使用 NSCoding 和 NSSecureCoding,但出于某种原因我总是会遇到错误:
The data couldn’t be read because it isn’t in the correct format.
...即使是我刚刚创建的。
我也尝试使用 NSKeyedUnarchiver.unarchivedObject(ofClasses: classes
但在我的 init.
这是我制作的展示问题的游乐场:
class CodingData: NSObject, NSCoding, NSSecureCoding {
static var supportsSecureCoding = true
var dic: [String: Int]!
var i: Int!
func encode(with coder: NSCoder) {
coder.encode(i, forKey: "i")
coder.encode(dic, forKey: "dic")
}
required convenience init?(coder: NSCoder) {
let anInt = coder.decodeObject(forKey: "i") as! Int
let anDic = coder.decodeObject(forKey: "dic") as! [String: Int]
self.init(dic: anDic, i: anInt)
}
init(dic: [String: Int], i: Int){
self.dic = dic
self.i = i
}
}
do{
let test = CodingData(dic: [:], i: 0)
//let classes = [NSDictionary.self, NSNumber.self]
let testData = try NSKeyedArchiver.archivedData(withRootObject: test, requiringSecureCoding: true)
let emptyDic = try NSKeyedUnarchiver.unarchivedObject(ofClass: CodingData.self, from: testData)
// Error here ^^^^^^
}catch{
error.localizedDescription
}
顺便说一句,不确定它是否重要但是在尝试调试 init 中的 coder
时它总是说(可能只是一个错误):
error: <EXPR>:1:1: error: non-nominal type '$__lldb_context' (aka 'Self') cannot be extended
extension $__lldb_context {
^ ~~~~~~~~~~~~~~~
error: <EXPR>:19:27: error: value of type 'Self' has no member '$__lldb_wrapped_expr_28'
$__lldb_injected_self.$__lldb_wrapped_expr_28(
~~~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~
您已经很努力了,但是您的代码有很多错误,我认为最简单的回答方法就是更正它:
class CodingData: NSObject, NSSecureCoding {
static var supportsSecureCoding = true
var dic: [String: Int]
var i: Int
func encode(with coder: NSCoder) {
coder.encode(i as NSNumber, forKey: "i")
coder.encode(dic as NSDictionary, forKey: "dic")
}
required init?(coder: NSCoder) {
let anInt = coder.decodeObject(of: NSNumber.self, forKey: "i")
let anDic = coder.decodeObject(of: NSDictionary.self, forKey: "dic")
self.dic = anDic as! [String:Int]
self.i = anInt as! Int
}
init(dic: [String: Int], i: Int){
self.dic = dic
self.i = i
}
}
现在可以使用了:
let test = CodingData(dic: [:], i: 0)
let testData = try NSKeyedArchiver.archivedData(withRootObject: test, requiringSecureCoding: true)
let emptyDic = try NSKeyedUnarchiver.unarchivedObject(ofClass: CodingData.self, from: testData)
print(emptyDic?.dic as Any, emptyDic?.i as Any) // Optional([:]) Optional(0)
所以你的四个主要错误是:
不要将实例 属性 声明为隐式展开的可选 (
!
)init?(coder:)
不是convenience
初始值设定项要进行安全编码,您必须使用安全编码 (
decodeObject(of:forKey:)
) 对每个编码的 属性 进行解码
只有 NSSecureCoding 类型可以使用安全编码进行编码,因此 Swift 类型必须转换为其 Objective-C 等价物