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()
и привязкой необработанного указателя к указателю UInt8
(см. Также Запись данных в NSOutputStream в 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()
}