2016-07-06 21 views
4

Ich habe gerade Xcode auf 8.0 Beta 2 und Swift 3.0 aktualisiert. Nach dem Update von swift 2.3 bekomme ich viele Fehler.Swift 3; Reichweite 'Out of Bounds'

Ich habe eine String-Erweiterung, die eine Reichweite im "Selbst" -string zu einem NSRange Converting:

extension String { 

    func NSRangeFromRange(_ range : Range<String.Index>) -> NSRange { 

     let utf16view = self.utf16 
     let from = String.UTF16View.Index(range.lowerBound, within: utf16view) 
     let to = String.UTF16View.Index(range.upperBound, within: utf16view) 

     print("to: \(to) from: \(from)") 
     print(self.characters.count) 

     return NSMakeRange(utf16view.startIndex.distance(to: from), from.distance(to: to)) 
    // return NSMakeRange(0, 0) // <-- removes exception 
    } 
} 

Wenn NSMakeRange ausgeführt wird, ich bin eine Störung zu erhalten:

Terminating app due to uncaught exception 'NSRangeException', reason: 'NSMutableRLEArray objectAtIndex:effectiveRange:: Out of bounds'

wenn ich die to- bin Druck und aus-Index ist, erhalte ich:

to: Index(_offset: 194) from: Index(_offset: 181)

die Zeichenzahl des String ist 210, die ungefähr richtig scheint.

Also, ich verstehe nicht, warum es mir sagt, dass der Index außerhalb der Grenzen sind, wenn sie weniger als die Gesamtzahl sind.

Diese Linie wurde perfekt funktioniert, bevor ich es sah aus wie das damals zu swift 3. aktualisiert:

return NSMakeRange(utf16view.startIndex.distanceTo(from), from.distanceTo(to)) 

Der Auto-Konverter nicht die Syntax von swift 2,3-3,0 aktualisiert wurde, habe ich das ist selbst.

Irgendwelche Hinweise?

+0

ich den 'Bereich ' '<-> NSRange' Konverter unter http aktualisiert: // stackov erflow.com/a/30404532/1187415 für Swift 3, hilft das? –

+0

Super .. Sie rocken.! So fand ich heraus, dass das Problem darin bestand, dass NSMakeRange Argumente von und zu nahm, wobei es wie in swift 3 Argumente von und Länge braucht. Dies verursachte die Ausnahmebedingung Ausnahme. – Wiingaard

+0

Ich glaube nicht, dass NSMakeRange das Problem ist, das immer loc/len Parameter genommen hat. –

Antwort

7

In Swift 3, "Sammlungen bewegen ihren Index", siehe A New Model for Collections and Indices auf Swift Evolution.

In Swift 2.2, die advancedBy() und distanceTo() Methoden auf dem Index genannt:

let u16 = "12345".utf16 
let i1 = u16.startIndex.advancedBy(1) 
let i2 = u16.startIndex.advancedBy(3) 
let d = i1.distanceTo(i2) 
print(d) // 2 

Diese Methode gibt es noch in Swift 3 aber zu unerwarteten Ergebnissen führen, zumindest auf den Charakter Kollektionen:

let u16 = "12345".utf16 
let i1 = u16.startIndex.advanced(by: 1) 
let i2 = u16.startIndex.advanced(by: 3) 
let d = i1.distance(to: i2) 
print(d) // -2 

Die korrekte Methode besteht darin, die index() und distance() Methoden der Sammlung selbst zu verwenden:

let u16 = "12345".utf16 
let i1 = u16.index(u16.startIndex, offsetBy: 1) 
let i2 = u16.index(u16.startIndex, offsetBy: 3) 
let d = u16.distance(from: i1, to: i2) 
print(d) // 2 

für Ihr Problem angewendet wird, das ist, wie Sie können ein Range<String.Index> zu dem entsprechenden NSRange in Swift 3 (von https://stackoverflow.com/a/30404532/1187415 kopiert) konvertieren:

extension String { 
    func nsRange(from range: Range<String.Index>) -> NSRange { 
     let utf16view = self.utf16 
     let from = range.lowerBound.samePosition(in: utf16view) 
     let to = range.upperBound.samePosition(in: utf16view) 
     return NSMakeRange(utf16view.distance(from: utf16view.startIndex, to: from), 
           utf16view.distance(from: from, to: to)) 
    } 
} 

Und der Vollständigkeit halber, ist dies die entgegengesetzte Umwandlung

extension String { 
    func range(from nsRange: NSRange) -> Range<String.Index>? { 
     guard 
      let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex), 
      let to16 = utf16.index(from16, offsetBy: nsRange.length, limitedBy: utf16.endIndex), 
      let from = String.Index(from16, within: self), 
      let to = String.Index(to16, within: self) 
     else { return nil } 
     return from ..< to 
    } 
}