var dataFile: NSData = NSMutableData.init(data: wav.subdataWithRange(NSRange.init(location: currentByte,length: wavDataSize)))
如何将此代码转换为使用Swift 3数据?或者如何将NSRange解析为Range
解决方法
假设
答案是Swift 3& 4个等效的问题代码.它将产生相同的结果dataFile,给定相同的输入值:wav,currentByte和wavDataSize,假设周围的代码没有变化.
我没有假设变量:wav,dataFile,currentByte或wavDataSize是什么意思.为避免变量名暗示问题中未说明的内容,我将使用以下名称:sourceData,subdata,rangeStartByte和subdataLength.我假设围绕此问题的代码(未在问题中显示)将确保rangeStartByte和subdataLength处于有效范围内以避免错误.
将NSRange转换为Range< Int>
问题中的Swift 2实现使用由起点和长度定义的NSRange,如下所示:
NSRange.init(location: rangeStartByte,length: subdataLength)
Swift 3&我建议的4实现创建一个等效的Range< Int>由起点和终点定义,如下所示:
rangeStartByte ..< (rangeStartByte + subdataLength)
我将一个应用程序从Swift 2.2转换为3,它使用类似的代码以较小的块上传照片.在转换过程中,我们错过了这个细微差别,并使用Swift 2实现的长度来代替Swift 3& 4实施的终点.这导致了一个难以解决的缺陷.第一次迭代成功但后续迭代失败.
另一个答案实现了我刚才描述的问题解决方案.它使用Swift 2范围长度的subdataLength作为Swift 3& 3的终点. 4个范围.这将在currentByte为0且subdataLength为< = NSData实例的长度的特殊情况下产生相同的结果(这就是我所描述的问题中第一次迭代成功的原因).该假设未在问题中明确说明,并为其他人提供了不太灵活的解决方案. Swift 3& 4当量
var subdata = sourceData.subdata(in: rangeStartByte ..< (rangeStartByte + subdataLength))
Swift 2.2
var subdata: NSData = NSMutableData.init(data: sourceData.subdataWithRange(NSRange.init(location: rangeStartByte,length: subdataLength)))
可运行的示例代码
我已经包含了可以在游乐场中运行的示例代码,演示了如何使用这一行代码将Data实例分离到较小的Data实例中.源数据实例是从字符串“ABCDEFGHIJKL”创建的.此实例分为长度为5的较小数据实例.
Swift 3& 4与上下文
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'
Swift 2.2带有上下文
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,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'
Swift 3& 4使用NSRange
pedrouan的回答使用NSRange这样:
var subdata: Data = Data(sourceData.subdata(with: NSRange(location: rangeStartByte,length: subdataLength)))
我最初无法编译,所以我忽略了它.现在我意识到,如果在NSData而不是Data声明或转换sourceData,它会起作用
如果您想在上面的“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))
我尽量不使用像NSRange这样的“NS”类,所以我赞成使用Swift Range的解决方案.