encodeObject(_:forKey:)在NSCoder接受AnyObject?类型:
func encodeObject(_ objv: AnyObject?, forKey key: String)
Run Code Online (Sandbox Code Playgroud)
所以,如果你通过数组Int来encodeObject,它隐式转换NSArray的NSNumber秒.该机制在文档中解释:
当您从Swift数组桥接到
NSArray对象时,Swift数组中的元素必须AnyObject兼容.例如,类型的Swift数组[Int]包含Int结构元素.该Int类型是不是一个类的实例,但由于Int类型桥梁的NSNumber类中,Int类型是AnyObject兼容的.因此,您可以将Swift数组类型桥[Int]接到NSArray对象.
在另一方面UInt8是不 AnyObject兼容的:
以下所有类型都自动桥接到
NSNumber:
- 诠释
- UINT
- 浮动
- 双
- 布尔
这就是为什么你不能传递[UInt8]到encodeObject(_:forKey:).您必须手动转换它.
如果您担心编码数据大小,则应使用NSData或原始字节数组而不是NSArray.实际上,这取决于NSCoder你使用的是哪个,但例如NSKeyedArchiver:
// NSData
class Foo: NSObject, NSCoding {
var _array: [UInt8]
init(array:[UInt8]) {
_array = array
}
required init(coder aDecoder: NSCoder) {
let arrayData = aDecoder.decodeObjectForKey("array") as NSData
_array = Array(
UnsafeBufferPointer(
start: UnsafePointer<UInt8>(arrayData.bytes),
count: arrayData.length
)
)
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(
NSData(bytes: _array, length: _array.count),
forKey: "array"
)
}
}
// bytes
class Bar: NSObject, NSCoding {
var _array: [UInt8]
init(array:[UInt8]) {
_array = array
}
required init(coder aDecoder: NSCoder) {
var arrayLength:Int = 0
var buf = aDecoder.decodeBytesForKey("array", returnedLength: &arrayLength)
_array = Array(UnsafeBufferPointer(start: buf, count: arrayLength))
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeBytes(_array, length: _array.count, forKey: "array")
}
}
// NSArray of NSNumber
class Baz: NSObject, NSCoding {
var _array: [UInt8]
init(array:[UInt8]) {
_array = array
}
required init(coder aDecoder: NSCoder) {
_array = (aDecoder.decodeObjectForKey("array") as [NSNumber]).map({ $0.unsignedCharValue })
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(_array.map({NSNumber(unsignedChar:$0)}), forKey:"array")
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
let array = [UInt8](0 ..< 255)
let foo = Foo(array: array)
let bar = Bar(array: array)
let baz = Baz(array: array)
let fooData = NSKeyedArchiver.archivedDataWithRootObject(foo)
let barData = NSKeyedArchiver.archivedDataWithRootObject(bar)
let bazData = NSKeyedArchiver.archivedDataWithRootObject(baz)
fooData.length // -> 539
barData.length // -> 534
bazData.length // -> 3,454
let fooCopy = NSKeyedUnarchiver.unarchiveObjectWithData(fooData) as Foo
let barCopy = NSKeyedUnarchiver.unarchiveObjectWithData(barData) as Bar
let bazCopy = NSKeyedUnarchiver.unarchiveObjectWithData(bazData) as Baz
Run Code Online (Sandbox Code Playgroud)
NSArray 是大约7倍的空间消耗.