objective-c - Swift 5 中的 NSData.bytes[下标]

标签 objective-c swift

我正在尝试将这段代码转换为 Swift:

NSData *testData = [@"Whatever" dataUsingEncoding:NSUTF8StringEncoding];
    void (^whatever)(NSOutputStream *) = ^(NSOutputStream *stream) {
        [stream open];
        NSRange myRange = {0};
        while (myRange.location < testData.length) {
            myRange.location += myRange.length;
            myRange.length = 4096;

            if (myRange.location + myRange.length > testData.length) {
                myRange.length = testData.length - myRange.location;
            }

            [stream write:&(testData.bytes[myRange.location])
                       maxLength:myRange.length];
        }
        [stream close];
    };

不幸的是,我真的卡在了 &(testData.bytes[myRange.location]) 上。

我在网上找到的 swift 转换器根本不处理那部分,Swift 编译器提示说:

Value of type 'UnsafeRawPointer' has no subscripts

带有 .withUnsafeBytes 的示例没有显示如何获取特定位置的字节指针。

这是 swift :

        let testData = "Whatever".data(using: .utf8)!
        let whatever: ((OutputStream) -> Void)? = { stream in
            stream.open()
            var myRange = NSRange()
            while myRange.location < testData.count {
                myRange.location += myRange.length
                myRange.length = 4096

                if myRange.location + myRange.length > testData.count {
                    myRange.length = testData.count - myRange.location
                }
                // the next line doesn't work
                stream.write(testData.bytes[myRange.location], maxLength: myRange.length)
            }
            stream.close()
        }

最佳答案

Objective-C 是 C 的超集,其中获取下标指针的地址相当于为指针添加偏移量:

&pointer[index] == pointer + index

在你的情况下,

[stream write:&(testData.bytes[myRange.location]) maxLength:myRange.length];

相当于

[stream write:testData.bytes + myRange.location maxLength:myRange.length];

这表明问题不在于下标,而在于如何获取指向偏移量处的 Data 值的元素存储的指针。

获取指向元素存储的指针是使用 withUnsafeBytes() 并将原始指针绑定(bind)到 UInt8 指针(另请参见 Writing Data to an NSOutputStream in Swift 3)。这可以与切片 (testData[offset...]) 相结合,以将数据写入指定的偏移量:

let testData = "Whatever".data(using: .utf8)!
let whatever: ((OutputStream) -> Void)? = { stream in
    stream.open()
    var position = 0
    while position < testData.count {
        let length = min(4096, testData.count - position)
        let amount =  testData[position...].withUnsafeBytes {
            stream.write($0.bindMemory(to: UInt8.self).baseAddress!, maxLength: length)
        }
        if amount <= 0 {
            // Error or EOF
            break
        }
        position += amount
    }
    stream.close()
}

请注意,write 方法返回实际写入的字节数(或0-1)。当写入除纯文件以外的任何内容(例如 TCP 套接字、管道...)时,这可能小于 maxLength 参数的值。

或者,您可以获得一次指向元素存储的指针,然后根据写入的数据量递增它:

let testData = "Whatever".data(using: .utf8)!
let whatever: ((OutputStream) -> Void)? = { stream in
    stream.open()
    var length = testData.count
    testData.withUnsafeBytes {
        var ptr = $0.bindMemory(to: UInt8.self).baseAddress!
        while length > 0 {
            let amount = stream.write(ptr, maxLength: min(length, 4096))
            if amount <= 0 { break }
            ptr += amount
            length -= amount
        }
    }
    stream.close()
}

关于objective-c - Swift 5 中的 NSData.bytes[下标],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58178709/

相关文章:

ios - 录制语音的按钮操作

objective-c - 使用 [NSBundle mainBundle] pathForResource : ofType:inDirectory: 访问文件

shell - swift 错误 : launch path not accessible

ios - UIImagePicker : How to always pick square image from camera library?

ios - 为什么这个硬编码的字符串没有被释放,而 alloc/inited 的字符串呢?

ios - 向左滑动时 subview 未被剪裁以删除 UITableViewCell

ios - 在 Swift 中阻止 : return error "is not convertible to "

objective-c - 处理 addPersistentStoreWithType 中的错误

ios - 如何将 NSstring 转换为 NSerror 对象类型

ios - 如何使用UIDocumentPickerViewController获得原始文件名?