我真的很难接受这样一个事实,someData[start...stop]返回一个MutableRandomAccessSlice。我的someData是一个let开始,那么为什么我想要一个可变的东西?为什么我不能得到一个RandomAccessSlice。但真正令人沮丧的是,它返回了一个与原始源不兼容的API。对于Data,我可以使用.withUnsafeBytes,但对于此子代则不是这样。你如何把切片变回数据也不清楚。没有一个init可以接受其中的一个。
我可以使用subdata(in:)方法而不是订阅,但是,如果我只希望子集合表示方式的行为与原始集合类似,那么订阅的要点是什么?而且,subdata方法只能做开子范围,为什么下标可以同时做闭子范围和开子范围。这就是他们还没有完成的东西吗?

最佳答案

记住,您返回的MutableRandomAccessSlice是值类型,而不是引用类型。它只是意味着你可以修改它,如果你喜欢的话,但它与你切下来的东西无关:

let x = Data(bytes: [1,2,3]) // <010203>
var y = x[0...1]
y[0] = 2
x // <010203>

如果您查看code,您将注意到其目的是返回自定义切片类型:
public subscript(bounds: Range<Index>) -> MutableRandomAccessSlice<Data> {
    get {
        return MutableRandomAccessSlice(base: self, bounds: bounds)
    }
    set {
        // Ideally this would be:
        //   replaceBytes(in: bounds, with: newValue._base)
        // but we do not have access to _base due to 'internal' protection
        // TODO: Use a custom Slice type so we have access to the underlying data
        let arrayOfBytes = newValue.map { $0 }
        arrayOfBytes.withUnsafeBufferPointer {
            let otherData = Data(buffer: $0)
            replaceBytes(in: bounds, with: otherData)
        }
    }
}

也就是说,自定义切片对于接受数据的函数仍然是不可接受的。不过,这与其他类型(如array)是一致的,后者切片到arrayslice,而arrayslice不能在需要数组的地方传递。这是按设计的(而且很可能是出于同样的原因,对于数据也是如此)。问题在于,一个切片“固定”了所有支持它的内存。因此,如果从一个兆字节数据中取出一个3字节的切片,并将其存储在一个IVAR中,那么整个兆字节就必须挂起。理论(根据我采访过的swift devs)是数组可能是巨大的,所以你需要小心分割它们,而字符串通常要小得多,所以字符串可以分割成一个字符串。
根据我目前的经验,您通常需要subdata(in:)。我对它的实验是,它在速度上与切片非常相似,所以我相信它仍然是写时拷贝(但在我最初的测试中,它似乎也没有固定内存)。不过,到目前为止,我只在Mac上测试过。iOS设备上的性能差异可能更大。

关于swift - 数据< - > MutableRandomAccessSlice,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38063521/

10-14 23:25
查看更多