Swift编码UInt8

bor*_*ero 2 arrays numbers nscoding swift

为什么能够编码数组Int使用aCoder.encodeObject(myIntArray, forKey: "myKey"),但是你想编码的数组时,编译器错误UInt8值?转换实际上并不是戏剧性的,但我会有56个不必要的Bits来编码......

rin*_*aro 6

encodeObject(_:forKey:)NSCoder接受AnyObject?类型:

func encodeObject(_ objv: AnyObject?, forKey key: String)
Run Code Online (Sandbox Code Playgroud)

所以,如果你通过数组IntencodeObject,它隐式转换NSArrayNSNumber秒.该机制在文档中解释:

当您从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倍的空间消耗.