繁体   English   中英

Swift编码UInt8

[英]Swift encode UInt8

为什么可以使用aCoder.encodeObject(myIntArray, forKey: "myKey")Int数组进行编码aCoder.encodeObject(myIntArray, forKey: "myKey")但是在尝试对UInt8值数组进行编码时会出现编译器错误? 转换实际上并不算是戏剧性的,但是我将有56个不必要的位要编码...

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

func encodeObject(_ objv: AnyObject?, forKey key: String)

因此,如果将Int数组传递给encodeObject ,则它将隐式转换为NSNumberNSArray 该机制在文档中进行解释:

从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倍的空间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM