在Swift 3中提取Data对象的片段

Chi*_*Sky 5 ios swift swift3

我有一个60字节的Data流如下

let myDataStream = Data(bytes: [24, 163, 209, 194, 255, 1, 184, 230, 37, 208, 140, 201, 6, 0, 64, 0, 7, 98, 108, 117, ...])
Run Code Online (Sandbox Code Playgroud)

字节#1(索引0)表示第一个对象的长度,因此在这种情况下,第一个对象由前24个对象组成,包括字节#1

我尝试了很多方法,但我一直无法弄清楚

  1. 如何将前24个字节提取到新的Data对象中

  2. 如何从myDataStream#1中删除前24个字节已经完成.字节#25将再次具有下一个对象的大小

我最接近解决#1的是

let streamLength = Int(myDataStream[0])
let newStream = Data(bytes: myDataStream[0...streamLength])
Run Code Online (Sandbox Code Playgroud)

但我得到一个错误说明 cannot invoke initializer for Data with Data.subsequence

Rya*_* H. 8

您可以结合使用subdataremoveSubRange方法来实现所需的结果.

subData(in:)Data结构上的实例方法.

removeSubRange()也是Data结构上的实例方法.

您可以在此处阅读有关这些方法的更多信息:https://developer.apple.com/reference/foundation/data

示例方法:

func extract(from data: inout Data) -> Data? {
    guard data.count > 0 else {
        return nil
    }

    // Define the length of data to return
    let length = Int.init(data[0])

    // Create a range based on the length of data to return
    let range = Range(0..<length)

    // Get a new copy of data
    let subData = data.subdata(in: range)

    // Mutate data
    data.removeSubrange(range)

    // Return the new copy of data
    return subData
}
Run Code Online (Sandbox Code Playgroud)

用法:

// Data (27 bytes)
var data = Data(bytes: [24, 163, 209, 194, 255, 1, 184, 230, 37, 208, 140, 201, 6, 0, 64, 0, 7, 98, 108, 117, 42, 63, 78, 200, 3, 34, 36])

// First extraction
let first = extract(from: &data)
print(first!) // Prints 24 bytes
print(data) // Prints 3 bytes

// Second extraction
let second = extract(from: &data)
print(second!) // Prints 3 bytes
print(data) // Prints 0 bytes

// Third extraction
let third = extract(from: &data)
print(third ?? "No Data") // Prints "No Data"
Run Code Online (Sandbox Code Playgroud)

进行扩展

您还可以将extract上面的方法包装在以下扩展名中Data:

extension Data {
    mutating func extract() -> Data? {
        guard self.count > 0 else {
            return nil
        }

        // Define the length of data to return
        let length = Int.init(self[0])

        // Create a range based on the length of data to return
        let range = Range(0..<length)

        // Get a new copy of data
        let subData = self.subdata(in: range)

        // Mutate data
        self.removeSubrange(range)

        // Return the new copy of data
        return subData
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这样的方法:

// Data (27 bytes)
var data = Data(bytes: [24, 163, 209, 194, 255, 1, 184, 230, 37, 208, 140, 201, 6, 0, 64, 0, 7, 98, 108, 117, 42, 63, 78, 200, 3, 34, 36])

// First extraction
let first = data.extract()
print(first!) // Prints 24 bytes
print(data) // Prints 3 bytes

// Second extraction
let second = data.extract()
print(second!) // Prints 3 bytes
print(data) // Prints 0 bytes

// Third extraction
let third = data.extract()
print(third ?? "No Data") // Prints "No Data"
Run Code Online (Sandbox Code Playgroud)


vad*_*ian 5

Data有专门的功能来处理subdata

let streamLength = Int(myDataStream[0])
let newStream = myDataStream.subdata(in: 1..<streamLength + 1)
let nextStream = myDataStream.subdata(in: streamLength + 1..<myDataStream.count)
Run Code Online (Sandbox Code Playgroud)