在我的应用中,我正在做这样的事情:
struct Record {
var exampleData : String
}
class ExampleClass : UIViewController {
let records = [Record]()
override func viewDidLoad() {
super.viewDidLoad()
let data = NSKeyedArchiver.archivedDataWithRootObject(self.records) as! NSData
}
...
}
但是在viewDidLoad()
的最后一行我收到了这个错误:
参数类型'[Record]'不符合预期类型'AnyObject'
我该如何解决这个问题?感谢。
答案 0 :(得分:7)
如果您想保留struct
,可以使用withUnsafePointer()
对数据进行编码。这是一个例子,我改编自this Gist:
import UIKit
enum EncodingStructError: ErrorType {
case InvalidSize
}
func encode<T>(var value: T) -> NSData {
return withUnsafePointer(&value) { p in
NSData(bytes: p, length: sizeofValue(value))
}
}
func decode<T>(data: NSData) throws -> T {
guard data.length == sizeof(T) else {
throw EncodingStructError.InvalidSize
}
let pointer = UnsafeMutablePointer<T>.alloc(1)
data.getBytes(pointer, length: data.length)
return pointer.move()
}
enum Result<T> {
case Success(T)
case Failure
}
我添加了一些错误处理,并将方法标记为throws
。在do
... catch
块中,您可以使用以下一种方式:
var res: Result<String> = .Success("yeah")
var data = encode(res)
do {
var decoded: Result<String> = try decode(data)
switch decoded {
case .Failure:
"failure"
case .Success(let v):
"success: \(v)" // => "success: yeah"
}
} catch {
print(error)
}
如果NSData
长度与类型大小不匹配,我添加的错误处理将不会解码。如果您将数据写入磁盘,用户使用相同类型的不同大小版本更新到较新版本的应用程序,然后读入数据,则通常会发生这种情况。
另请注意,sizeof()
和sizeofValue()
可能会在不同的设备上返回不同的值,因此这不是在设备之间发送数据的绝佳解决方案(NSJSONSerialization
可能更适合)。
答案 1 :(得分:3)
AnyObject
表示任何引用类型对象,主要是类。 struct
是值类型,无法传递给需要AnyObject
的函数。 Any
可用于接受值类型和引用类型。要修复上述代码,请将struct Record
更改为class Record
。但我有一种感觉,你可能想要出于其他原因使用结构。您可以围绕Record
创建一个类包装器,您可以将其转换为来源,以用于需要AnyObject
的函数。
答案 2 :(得分:1)
我做了类似的事情:
static func encode<T>(value: T) -> NSData {
var val = value
return withUnsafePointer(to: &val) { pointer in
NSData(bytes: pointer, length: MemoryLayout.size(ofValue: val))
}
}
static func decode<T>(data: NSData) -> T {
guard data.length == MemoryLayout<T>.size.self else {
fatalError("[Credential] fatal unarchiving error.")
}
let pointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
data.getBytes(pointer, length: data.length)
return pointer.move()
}