我正在尝试将这段代码转换为 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/