it-swarm.com.de

Wie funktioniert String.Index in Swift?

Ich habe ein paar meiner alten Codes und Antworten mit Swift 3 aktualisiert, aber als ich zu Swift Strings und Indexing kam, war es ein Schmerz, Dinge zu verstehen. 

Im Einzelnen habe ich folgendes versucht:

let str = "Hello, playground"
let prefixRange = str.startIndex..<str.startIndex.advancedBy(5) // error

wo die zweite Zeile mir den folgenden Fehler gab

'advancedBy' ist nicht verfügbar: Um einen Index um n Schritte vorzurücken, rufen Sie 'index (_: offsetBy :)' für die CharacterView-Instanz auf, die den Index erstellt hat.

Ich sehe, dass String die folgenden Methoden hat.

str.index(after: String.Index)
str.index(before: String.Index)
str.index(String.Index, offsetBy: String.IndexDistance)
str.index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)

Das hat mich anfangs wirklich verwirrt, also habe ich angefangen, mit ihnen herumzuspielen, bis ich sie verstanden habe. Ich füge unten eine Antwort hinzu, um zu zeigen, wie sie verwendet werden.

74
Suragch

 enter image description here

Alle folgenden Beispiele verwenden 

var str = "Hello, playground"

startIndex und endIndex

  • startIndex ist der Index des ersten Zeichens
  • endIndex ist der Index nach das letzte Zeichen.

Beispiel

// character
str[str.startIndex] // H
str[str.endIndex]   // error: after last character

// range
let range = str.startIndex..<str.endIndex
str[range]  // "Hello, playground"

Mit Swift 4 einseitigen Bereichen kann der Bereich auf eine der folgenden Formen vereinfacht werden.

let range = str.startIndex...
let range = ..<str.endIndex

Ich werde das vollständige Formular in den folgenden Beispielen aus Gründen der Klarheit verwenden, aus Gründen der besseren Lesbarkeit sollten Sie jedoch wahrscheinlich die einseitigen Bereiche in Ihrem Code verwenden.

after

Wie in: index(after: String.Index)

  • after bezieht sich auf den Index des Zeichens direkt nach dem angegebenen Index.

Beispiele

// character
let index = str.index(after: str.startIndex)
str[index]  // "e"

// range
let range = str.index(after: str.startIndex)..<str.endIndex
str[range]  // "Ello, playground"

before

Wie in: index(before: String.Index)

  • before bezieht sich auf den Index des Zeichens direkt vor dem angegebenen Index.

Beispiele

// character
let index = str.index(before: str.endIndex)
str[index]  // d

// range
let range = str.startIndex..<str.index(before: str.endIndex)
str[range]  // Hello, playgroun

offsetBy

Wie in: index(String.Index, offsetBy: String.IndexDistance)

  • Der offsetBy-Wert kann positiv oder negativ sein und beginnt am angegebenen Index. Obwohl es vom Typ String.IndexDistance ist, können Sie ihm eine Int geben.

Beispiele

// character
let index = str.index(str.startIndex, offsetBy: 7)
str[index]  // p

// range
let start = str.index(str.startIndex, offsetBy: 7)
let end = str.index(str.endIndex, offsetBy: -6)
let range = start..<end
str[range]  // play

limitedBy

Wie in: index(String.Index, offsetBy: String.IndexDistance, limitedBy: String.Index)

  • Die Variable limitedBy ist nützlich, um sicherzustellen, dass der Offset nicht dazu führt, dass sich der Index außerhalb der Grenzen befindet. Es ist ein Begrenzungsindex. Da es möglich ist, dass der Versatz den Grenzwert überschreitet, gibt diese Methode eine Option zurück. Es gibt nil zurück, wenn der Index außerhalb der Grenzen liegt.

Beispiel

// character
if let index = str.index(str.startIndex, offsetBy: 7, limitedBy: str.endIndex) {
    str[index]  // p
}

Wenn der Versatz 77 anstelle von 7 gewesen wäre, wäre die if-Anweisung übersprungen worden.

Warum wird String.Index benötigt?

Es wäre viel einfacher, einen Int-Index für Strings zu verwenden. Der Grund dafür, dass Sie einen neuen String.Index für jeden String erstellen müssen, ist, dass die Zeichen in Swift nicht alle unter der Haube gleich lang sind. Ein einzelnes Swift-Zeichen kann aus einem, zwei oder sogar mehr Unicode-Codepunkten bestehen. Daher muss jeder eindeutige String die Indizes seiner Zeichen berechnen.

Es ist möglich, diese Komplexität hinter einer Int-Indexerweiterung zu verbergen, aber ich zögere, dies zu tun. Es ist gut, daran erinnert zu werden, was tatsächlich passiert.

204
Suragch

Ich stand vor dem gleichen Problem und bekam eine Lösung, die meinen Bedürfnissen entspricht. Ich habe eine UITextView in einem tableViewController. Ich verwendete die Funktion: textViewDidChange und überprüfte dann die Return-Key-Eingabe. Wenn dann die Return-Key-Eingabe erkannt wurde, löschte ich die Eingabe der Return-Taste und schloss die Tastatur ab.

func textViewDidChange(_ textView: UITextView) {
    tableView.beginUpdates()
    if textView.text.contains("\n"){
        textView.text.remove(at: textView.text.index(before: textView.text.endIndex))
        textView.resignFirstResponder()
    }
    tableView.endUpdates()
}
0
Karl Mogensen