2016-08-11 1 views
2

Vielleicht ist dies ein Xcode 8 Beta Problem jedoch vor 2.2 die var Schlüsselwort ist erlaubt Parameter in Funktion Signaturen vorangestellt wird:Wie können veränderbare Parameter in Verschlüssen mit Swift> 2.2 bezeichnet werden?

func (var stringName: String) { ... } 

Dies hat statt der dort sein wenig Vorteil gegenüber inout veraltet seitdem

func (stringName: inout String) { ... } 

ich habe folgendes in einem map Schließung versucht, und obwohl ich als eine deprecation Warnung erhalten keine milde erwartete ich sollte, der Fehler war eher ein segmentation fault: 11

Der Fehler tritt auf, sobald ich versuche, die (mutmaßlich veränderliche) Variable word zu mutieren.

Ich habe andere Variation versucht, z. mit inout

let demoString = ["hi", "there", "world"].map { (word: inout String) -> String in 
    let firstChar = word.remove(at: word.startIndex) 
} 

Aber der Compiler beschwert sich, dass diese fälschlicherweise die Unterschrift des Verschlusses insgesamt ändert sich und wird nicht kompiliert.

Offensichtlich ist die Abhilfe einfach die Variable auf einem lokalen innerhalb des Verschlusses zu kopieren:

let demoString = ["hi", "there", "world"].map { (word) -> String in 
    let tempWord = word 
    let firstChar = tempWord.remove(at: tempWord.startIndex) 
} 

aber ich bin daran interessiert zu wissen, ob diese Funktionalität erwartet wird &, ob es ist eine Möglichkeit, einen Parameter mutieren, der direkt in einen Abschluss übergeben wurde?

+0

Hat sich Ihre Frage beantwortet? – Alexander

Antwort

3

Closures inout Argumente mutieren kann ganz gut:

var str1 = "Pine" 
var str2 = "Juniper" 

let closure = { (s1: inout String, s2: inout String) -> Void in 
    s1 = "Oak" 
    s2 = "Chestnut" 
} 

closure(&str1, &str2) 

print(str1, str2) 

Das Problem Sie konfrontiert sind ist Array.map nicht funktioniert haben Sie eine Methodensignatur, die einen inout Parameter enthält .

Der einzige Weg, um dieses, das ich denken kann, ist Array zu erweitern und fügen Sie die map Methode selbst:

extension Array { 
    func map<T>(_ closure: (inout T) -> Void) -> Array<T> { 
     var arr = [T]() 
     for i in 0..<self.count { 
      var temp : T = self[i] as! T 
      closure(&temp) 
      arr.append(temp) 
     } 
     return arr 
    } 
} 

var hi = "hi", there = "there", world = "world" 
var demoStrings = [hi, there, world] 
var result = demoStrings.map { (word: inout String) in 
    word.remove(at: word.startIndex) 
} 

print(result) // ["i", "here", "orld"] 
0

Wie pro SE-0003var Parameter nicht mehr existieren in Swift 3.

Grundsätzlich sollten Sie nicht die Parameter aus map gegeben werden mutiert, sowieso. Stattdessen: Verwenden Sie nicht mutierende Funktionen oder erstellen Sie eine lokal veränderbare Kopie.

In diesem Fall gibt es keinen Grund, remove(_:) nur zu verwenden, um das erste Zeichen zu erhalten. Dies würde das Kopieren eines String-Speichers erfordern (das erste Zeichen wird weggelassen), nur um das entfernte Zeichen zu erhalten. Es ist ziemlich klobig.

In diesem Fall können Sie die first Instanzvariable (aus dem Collection Protokoll) erhalten nur auf der characters Instanz Eigenschaft von String.

Versuchen Sie folgendes:

let demoStrings = ["hi", "there", "world"] 

let firstLetters = demoStrings.map {(word: String) -> String in 
    return word.characters.first 
} 

oder kurz:

let firstLetters = demoStrings.map{ $0.characters.first } 
+0

Danke für den Kommentar. Ich suche nicht wirklich nach einer Möglichkeit, den Ausdruck umzuschreiben. Es ist nur für Demozwecke da. Ich versuche herauszufinden, ob die Parameter, die in die Schließungen gelangen, mutiert werden können. FYI 'word.characters.first' wenn alles, was Sie brauchen, der erste Buchstabe ist. –

+0

Oh natürlich, ich habe keine Ahnung, warum '.first' nicht in den Sinn kam lol – Alexander

+0

Sie können Verschlüsse mit' inout' Parametern haben, aber Sie können eine solche Schließung nicht für 'map' verwenden, wegen der Deklaration der Schließung der Karte (die nicht "inout" verwendet) – Alexander

Verwandte Themen