TGCBraun
TGCBraun

Reputation: 95

Cannot convert value of type 'NSRange'(aka'_NSRange') to expected argument type 'Range<Data.Index>' (aka 'Range<int>

there. I am a beginner in Swift and am trying to convert an older program to Swift3. I´ve managed to fix a bunch of errors, but I cannot get this function to work.

fileprivate func extractEntitlements(_ entitlementData: Data) -> NSDictionary? {
  var originalEntitlementsData = entitlementData
  let xmlStart = "<?xml".data(using: String.Encoding.ascii, allowLossyConversion: true)
  let bytes = (originalEntitlementsData as NSData).bytes
  for i in 0...(originalEntitlementsData.count - xmlStart!.count) {
     if memcmp((xmlStart! as NSData).bytes, bytes + i, Int(xmlStart!.count)) == 0 {
        let end = originalEntitlementsData.count - i
        **originalEntitlementsData = originalEntitlementsData.subdata(in: NSMakeRange(i, end))**
        break;
     }
  }

  return NSString(data: originalEntitlementsData, encoding: String.Encoding.ascii.rawValue)?.propertyList() as? NSDictionary

}

Here is the error I get:

Cannot convert value of type 'NSRange'(aka'_NSRange') to expected argument type 'Range<Data.Index>' (aka 'Range<int>')

There are a bunch of questions regarding this error, but I am not being successful implementing a solution. Any tips on how I should proceed?

Thanks guys!

Upvotes: 2

Views: 1588

Answers (2)

Martin R
Martin R

Reputation: 539745

As @jrturton already said, subdata(in:) takes a Range<Int> argument, so it should be

originalEntitlementsData = originalEntitlementsData.subdata(in: i..<i+end)

in your case. But note that all the conversions to NSData, taking the .bytes, explicit loop and memcmp are not needed if you take advantage of the existing range(of:) method of Data:

var originalEntitlementsData = entitlementData
let xmlStart = "<?xml".data(using: .utf8)!
if let range = originalEntitlementsData.range(of: xmlStart) {
    originalEntitlementsData = originalEntitlementsData.subdata(in: range.lowerBound..<originalEntitlementsData.endIndex)
   // Alternatively:
   // originalEntitlementsData.removeSubrange(0..<range.lowerBound)
}

Upvotes: 2

jrturton
jrturton

Reputation: 119242

Ranges are more complicated and simpler at the same time in swift.

You want subdata(in: start..<end), which makes a Range<Int>, which is the type you need. However, in this case start and end refer to the beginning and end indexes of the range, not the location and length as you pass to NSMakeRange().

Upvotes: 4

Related Questions