Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何让NSCoder对Swift结构数组进行编码/解码?_Arrays_Swift_Serialization_Nscoding - Fatal编程技术网

Arrays 如何让NSCoder对Swift结构数组进行编码/解码?

Arrays 如何让NSCoder对Swift结构数组进行编码/解码?,arrays,swift,serialization,nscoding,Arrays,Swift,Serialization,Nscoding,我有一个必须符合NSCoding的对象,该对象包含UInt64值的数组。如何使用NSCoder对其进行编码/解码?额外的问题:我怎样才能最简洁地编码它?(它必须进入已保存的游戏中心状态数据,其大小是有限的。) 理想情况下,我只想写一个Int,它是数组的大小n,然后写n乘以aUInt64,并以类似方式读取它。我能做这个吗 coder.encodeObject(值,forKey:“v”)不起作用 class MyObject: NSCoding { private var values:

我有一个必须符合
NSCoding
的对象,该对象包含
UInt64
值的数组。如何使用
NSCoder
对其进行编码/解码?额外的问题:我怎样才能最简洁地编码它?(它必须进入已保存的游戏中心状态数据,其大小是有限的。)

理想情况下,我只想写一个
Int
,它是数组的大小
n
,然后写
n
乘以a
UInt64
,并以类似方式读取它。我能做这个吗

coder.encodeObject(值,forKey:“v”)
不起作用

class MyObject: NSCoding {

    private var values: [UInt64]

    // …

    // MARK: - NSCoding

    required init(coder decoder: NSCoder) {
        // ???
    }

    func encodeWithCoder(coder: NSCoder) {
        // ???
    }


}

下面是一个可能的解决方案,它将
UInt64
数组编码为 字节数组。它的灵感来源于对这些问题的回答


Swift 3的更新(代码8):

class MyObject: NSObject, NSCoding {

    var values: [UInt64] = []

    init(values : [UInt64]) {
        self.values = values
    }

    // MARK: - NSCoding
    required init(coder decoder: NSCoder) {
        super.init()
        var count = 0
        // decodeBytesForKey() returns an UnsafePointer<UInt8>?, pointing to immutable data.
        if let ptr = decoder.decodeBytes(forKey: "values", returnedLength: &count) {
            // If we convert it to a buffer pointer of the appropriate type and count ...
            let numValues = count / MemoryLayout<UInt64>.stride
            ptr.withMemoryRebound(to: UInt64.self, capacity: numValues) {
                let buf = UnsafeBufferPointer<UInt64>(start: UnsafePointer($0), count: numValues)
                // ... then the Array creation becomes easy.
                values = Array(buf)
            }
        }
    }

    public func encode(with coder: NSCoder) {
        // This encodes both the number of bytes and the data itself.
        let numBytes = values.count * MemoryLayout<UInt64>.stride
        values.withUnsafeBufferPointer {
            $0.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: numBytes) {
                coder.encodeBytes($0, length: numBytes, forKey: "values")
            }
        }
    }
}


let obj = MyObject(values: [1, 2, 3, UInt64.max])
let data = NSKeyedArchiver.archivedData(withRootObject: obj)

let dec = NSKeyedUnarchiver.unarchiveObject(with: data) as! MyObject
print(dec.values) // [1, 2, 3, 18446744073709551615]
类MyObject:NSObject,NSCoding{
变量值:[UInt64]=[]
初始化(值:[UInt64]){
self.values=值
}
//标记:-NSCoding
必需的初始化(编码器-解码器:NSCoder){
super.init()
变量计数=0
//decodeBytesForKey()返回指向不可变数据的非安全指针。
如果let ptr=decoder.decodeBytes(forKey:“值”,returnedLength:&count){
//如果我们将其转换为适当类型和计数的缓冲区指针。。。
让numValues=count/MemoryLayout.stride
带内存绑定的ptr(to:UInt64.self,容量:numValues){
让buf=UnsafeBufferPointer(开始:UnsafePointer($0),计数:numValues)
//…这样,阵列创建就变得简单了。
值=数组(buf)
}
}
}
公共函数编码(带编码器:NSCoder){
//这将对字节数和数据本身进行编码。
让numBytes=values.count*MemoryLayout.stride
values.withUnsafeBufferPointer{
$0.baseAddress!.withMemoryRebound(收件人:UInt8.self,容量:numBytes){
coder.encodeBytes($0,长度:numBytes,forKey:“值”)
}
}
}
}
设obj=MyObject(值:[1,2,3,UInt64.max])
let data=NSKeyedArchiver.archivedData(withRootObject:obj)
让dec=NSKeyedUnarchiver.unarchiveObject(带:data)为!肌体
打印(十二月值)/[1,2,3,18446744073709551615]

这里有一个可能的解决方案,将
UInt64
数组编码为 字节数组。它的灵感来源于对这些问题的回答


Swift 3的更新(代码8):

class MyObject: NSObject, NSCoding {

    var values: [UInt64] = []

    init(values : [UInt64]) {
        self.values = values
    }

    // MARK: - NSCoding
    required init(coder decoder: NSCoder) {
        super.init()
        var count = 0
        // decodeBytesForKey() returns an UnsafePointer<UInt8>?, pointing to immutable data.
        if let ptr = decoder.decodeBytes(forKey: "values", returnedLength: &count) {
            // If we convert it to a buffer pointer of the appropriate type and count ...
            let numValues = count / MemoryLayout<UInt64>.stride
            ptr.withMemoryRebound(to: UInt64.self, capacity: numValues) {
                let buf = UnsafeBufferPointer<UInt64>(start: UnsafePointer($0), count: numValues)
                // ... then the Array creation becomes easy.
                values = Array(buf)
            }
        }
    }

    public func encode(with coder: NSCoder) {
        // This encodes both the number of bytes and the data itself.
        let numBytes = values.count * MemoryLayout<UInt64>.stride
        values.withUnsafeBufferPointer {
            $0.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: numBytes) {
                coder.encodeBytes($0, length: numBytes, forKey: "values")
            }
        }
    }
}


let obj = MyObject(values: [1, 2, 3, UInt64.max])
let data = NSKeyedArchiver.archivedData(withRootObject: obj)

let dec = NSKeyedUnarchiver.unarchiveObject(with: data) as! MyObject
print(dec.values) // [1, 2, 3, 18446744073709551615]
类MyObject:NSObject,NSCoding{
变量值:[UInt64]=[]
初始化(值:[UInt64]){
self.values=值
}
//标记:-NSCoding
必需的初始化(编码器-解码器:NSCoder){
super.init()
变量计数=0
//decodeBytesForKey()返回指向不可变数据的非安全指针。
如果let ptr=decoder.decodeBytes(forKey:“值”,returnedLength:&count){
//如果我们将其转换为适当类型和计数的缓冲区指针。。。
让numValues=count/MemoryLayout.stride
带内存绑定的ptr(to:UInt64.self,容量:numValues){
让buf=UnsafeBufferPointer(开始:UnsafePointer($0),计数:numValues)
//…这样,阵列创建就变得简单了。
值=数组(buf)
}
}
}
公共函数编码(带编码器:NSCoder){
//这将对字节数和数据本身进行编码。
让numBytes=values.count*MemoryLayout.stride
values.withUnsafeBufferPointer{
$0.baseAddress!.withMemoryRebound(收件人:UInt8.self,容量:numBytes){
coder.encodeBytes($0,长度:numBytes,forKey:“值”)
}
}
}
}
设obj=MyObject(值:[1,2,3,UInt64.max])
let data=NSKeyedArchiver.archivedData(withRootObject:obj)
让dec=NSKeyedUnarchiver.unarchiveObject(带:data)为!肌体
打印(十二月值)/[1,2,3,18446744073709551615]

非常感谢。是否有办法进一步优化输出数据的大小?或者我必须为此编写自己的NSCoder子类(或者可能使用)?@Jean Philippellet:我检查了归档数据,发现UInt64数组实际上存储为一个长度字节加上4*8字节,因此除非以某种方式“压缩”数据,否则无法进一步压缩。在没有阵列的情况下归档对象已导致226字节。我没有其他编码器的经验。非常感谢。是否有办法进一步优化输出数据的大小?或者我必须为此编写自己的NSCoder子类(或者可能使用)?@Jean Philippellet:我检查了归档数据,发现UInt64数组实际上存储为一个长度字节加上4*8字节,因此除非以某种方式“压缩”数据,否则无法进一步压缩。在没有阵列的情况下归档对象已导致226字节。我没有其他编码器的经验。
class MyObject: NSObject, NSCoding {

    var values: [UInt64] = []

    init(values : [UInt64]) {
        self.values = values
    }

    // MARK: - NSCoding
    required init(coder decoder: NSCoder) {
        super.init()
        var count = 0
        // decodeBytesForKey() returns an UnsafePointer<UInt8>?, pointing to immutable data.
        if let ptr = decoder.decodeBytes(forKey: "values", returnedLength: &count) {
            // If we convert it to a buffer pointer of the appropriate type and count ...
            let numValues = count / MemoryLayout<UInt64>.stride
            ptr.withMemoryRebound(to: UInt64.self, capacity: numValues) {
                let buf = UnsafeBufferPointer<UInt64>(start: UnsafePointer($0), count: numValues)
                // ... then the Array creation becomes easy.
                values = Array(buf)
            }
        }
    }

    public func encode(with coder: NSCoder) {
        // This encodes both the number of bytes and the data itself.
        let numBytes = values.count * MemoryLayout<UInt64>.stride
        values.withUnsafeBufferPointer {
            $0.baseAddress!.withMemoryRebound(to: UInt8.self, capacity: numBytes) {
                coder.encodeBytes($0, length: numBytes, forKey: "values")
            }
        }
    }
}


let obj = MyObject(values: [1, 2, 3, UInt64.max])
let data = NSKeyedArchiver.archivedData(withRootObject: obj)

let dec = NSKeyedUnarchiver.unarchiveObject(with: data) as! MyObject
print(dec.values) // [1, 2, 3, 18446744073709551615]