为什么可以使用Int
对aCoder.encodeObject(myIntArray, forKey: "myKey")
数组进行编码,但在尝试编码UInt8
值数组时会出现编译器错误?转换实际上并不是戏剧性的,但我会有56个不必要的Bits来编码...
答案 0 :(得分:6)
encodeObject(_:forKey:)
中的 NSCoder
接受AnyObject?
类型:
func encodeObject(_ objv: AnyObject?, forKey key: String)
因此,如果您将Int
数组传递给encodeObject
,则会隐式转换为NSArray
个NSNumber
。 the document:
当您从Swift数组桥接到
NSArray
对象时, Swift数组中的元素必须AnyObject
兼容。例如,类型为[Int]
的Swift数组包含Int
个结构元素。Int
类型不是类的实例,但由于Int
类型与NSNumber
类桥接,Int
类型与AnyObject
类型兼容。因此,您可以将类型为[Int]
的Swift数组桥接到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")
}
}
然后:
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
NSArray
大约占用了7倍的空间。