var dataFile: NSData = NSMutableData.init(data: wav.subdataWithRange(NSRange.init(location: currentByte, length: wavDataSize)))
如何将这段代码转换为使用 Swift 3 中的 Data
?或者如何将 NSRange
解析为 Range
?
var dataFile: NSData = NSMutableData.init(data: wav.subdataWithRange(NSRange.init(location: currentByte, length: wavDataSize)))
如何将这段代码转换为使用 Swift 3 中的 Data
?或者如何将 NSRange
解析为 Range
?
Data
分成较小的Data
实例这个答案是 Swift 3 和 4 版本中与问题代码等效的。它将产生相同的结果dataFile
,假设输入值相同: wav
, currentByte
和wavDataSize
,假设周围的代码没有更改。
我并不假设变量wav
、dataFile
、currentByte
或wavDataSize
的含义。为了避免变量名暗示未在问题中声明的东西,我将使用以下名称: sourceData
、subdata
、rangeStartByte
和subdataLength
。我假设(未在问题中显示)周围的代码将确保rangeStartByte
和subdataLength
处于有效范围内,以避免错误。
问题中的 Swift 2 实现使用由起点和长度定义的NSRange
,如下所示:
NSRange.init(location: rangeStartByte, length: subdataLength)
我提出的 Swift 3 & 4 实现方式创建了一个等价的 Range<Int>
,由起始点和结束点定义如下:
rangeStartByte ..< (rangeStartByte + subdataLength)
我将一个使用类似代码分块上传照片的Swift 2.2应用程序转换成了Swift 3。在转换过程中,我们忽略了这个细节,使用了Swift 2实现的长度来代替Swift 3和4实现的终点。这导致了一个难以解决的缺陷。第一次迭代成功了,但后续迭代失败了。
另一个答案描述了我刚才所描述问题的解决方案。它使用Swift 2范围的subdataLength
作为Swift 3和4范围的终点。在当前字节为0且subdataLength
小于NSData实例的长度的特殊情况下,这将产生相同的结果(这就是为什么在我描述的问题中第一次迭代成功的原因)。这个假设没有在问题中明确说明,并且为其他人提供了一个不太灵活的解决方案。
var subdata = sourceData.subdata(in: rangeStartByte ..< (rangeStartByte + subdataLength))
(问题中的代码,使用更新后的变量名称)
var subdata: NSData = NSMutableData.init(data: sourceData.subdataWithRange(NSRange.init(location: rangeStartByte, length: subdataLength)))
我在代码演示环境中提供了可以运行的示例代码,演示了如何使用这行代码将一个Data
实例分成更小的Data
实例。源Data
实例是从字符串"ABCDEFGHIJKL"
创建的。该实例被分割成长度为5的更小的Data
实例。
import UIKit
var sourceString = "ABCDEFGHIJKL"
let sourceData = sourceString.data(using: String.Encoding.utf8)! // sourceData is equivalent to "wav" from question
var rangeStartByte = 0 // rangeStartByte is equivalent to "currentByte" from question
let maxSubdataLength = 5
let dataLength = sourceString.lengthOfBytes(using: String.Encoding.utf8)
precondition(maxSubdataLength <= dataLength, "maxSubdataLength must be <= to dataLength")
while rangeStartByte < dataLength {
// subdataLength is equivalent to "wavDataSize" from question
let subdataLength = min(maxSubdataLength, dataLength - rangeStartByte)
// subdata is equivalent to "dataFile" from question
let subdata = Data(sourceData.subdata(in: rangeStartByte ..< (rangeStartByte + subdataLength)))
let subdataString = String(data: subdata, encoding: String.Encoding.utf8) ?? ""
print("'\(subdataString)'")
rangeStartByte += subdataLength
}
结果是:
'ABCDE'
'FGHIJ'
'KL'
import UIKit
var sourceString = "ABCDEFGHIJKL"
let sourceData = sourceString.dataUsingEncoding(NSUTF8StringEncoding)! // sourceData is equivalent to "wav" from question
var rangeStartByte = 0 // rangeStartByte is equivalent to "currentByte" from question
let maxSubdataLength = 5
let dataLength = sourceString.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
precondition(maxSubdataLength <= dataLength, "maxSubdataLength must be <= to dataLength")
while rangeStartByte < dataLength {
// subdataLength is equivalent to "wavDataSize" from question
let subdataLength = min(maxSubdataLength, dataLength - rangeStartByte)
// subdata is equivalent to "dataFile" from question
let subdata: NSData = NSMutableData.init(data: sourceData.subdataWithRange(NSRange.init(location: rangeStartByte, length: subdataLength)))
let subdataString = String(data: subdata, encoding: NSUTF8StringEncoding) ?? ""
print("'\(subdataString)'")
rangeStartByte += subdataLength
}
结果为:
'ABCDE'
'FGHIJ'
'KL'
pedrouan的回答如下所示:
var subdata: Data = Data(sourceData.subdata(with: NSRange(location: rangeStartByte, length: subdataLength)))
最初我无法使其编译,因此我忽略了它。现在我意识到,如果将sourceData
声明或转换为NSData
而不是Data
,它就可以工作。
如果您想在上面的“Swift 3&4 with context”示例代码中运行此方法,请使用此代码替换该示例中相应的代码:
// subdata is equivalent to "dataFile" from question
let sourceNSData = sourceData as NSData
let subdata = sourceNSData.subdata(with: NSRange(location: rangeStartByte, length: subdataLength))
我尽可能地避免使用"NS"类,比如NSRange,所以我更喜欢使用Swift Range的解决方案。
*** Terminating app due to uncaught exception 'NSRangeException'
,这是由于范围超过了数据长度所致。 - Max PotapovSwift 3.0中的一些“小”变化
var dataFile: Data = Data(wav.subdata(with: NSRange(location: currentByte, length: wavDataSize)))
。
var dataFile = sourceData.subdata(in: currentByte..<currentByte+wavDataSize)