2016-03-27 12 views
5

Es sieht so aus, als ob die folgende Swift-For-In-Schleife versucht, mehr Elemente durchzugehen als im Array.For-In-Schleife geht zu weit und findet 'Null' beim Entpacken

Zum Beispiel dieser Code:

var list:[Int?] = [1,2,3,4,5,6,7] 

print("C-Style for loop") 
for var i=0; i<list.count; i++ 
{ 
    var x:Int = list[i]! 
    print(x) 
} 

print("\nFor-in loop") 
for var x:Int! in list 
{ 
    print(x) 
} 

Ruft diese Ausgabe:

C-Style for loop 
1 
2 
3 
4 
5 
6 
7 

For each loop 
1 
2 
3 
4 
5 
6 
7 
fatal error: unexpectedly found nil while unwrapping an Optional value 
... 
Illegal instruction: 4 

ich hier etwas fehlt muss. Sollte nicht list.count die Anzahl der Elemente sein, die die For-In-Schleife zu entpacken versucht?

Nicht oben abgebildet funktioniert die For-In-Schleife wie erwartet, wenn Sie eine [Int]-Liste anstelle von [Int?] ohne Auspacken verwenden.

Ich bin auf Swift Version 2.1.1.

+0

ein seltsames Verhalten hier. Wenn Sie 'list' als' [Int] 'bezeichnen und dann' x' als 'Int?' Kennzeichnen, wird mit der 'for-in'-Schleife' nil' für immer gedruckt. – BallpointBen

+0

@Robert Dieses Verhalten ist nicht besonders merkwürdig, wenn Sie verstehen, wie es funktioniert ... aber Swift sollte wahrscheinlich einfach verhindern, dass 'x' als optionales Zeichen ist (weil es nur zu einer Endlosschleife führen kann). – nhgrif

+0

Können Sie kurz erklären, was los ist? Warum macht das eine Endlosschleife? – BallpointBen

Antwort

4

Im Grunde haben Sie etwas getan, was Sie nicht tun sollten, und so sind Sie auf etwas gestoßen, das wahrscheinlich ein Compiler Bug ist (weil der Compiler Sie nicht aufgehalten hat). Sehr schön!

Jetzt die Lösung. Sie versuchen offensichtlich, mit Ihrem Int! auszupacken. Auszupacken sicher verwenden for case Syntax:

let list:[Int?] = [1,2,3,4,5,6,7] 
for case let x? in list 
{ 
    print(x) // 1, 2, 3, 4, 5, 6, 7 
} 

andere Art und Weise (gleiche Ergebnis):

let list:[Int?] = [1,2,3,4,5,6,7] 
list.flatMap{$0}.forEach{print($0)} // 1, 2, 3, 4, 5, 6, 7 
+0

So forEach leidet das gleiche Problem ... gruselig. – Darko

+0

@Darko nein, tut es eigentlich nicht; das gibt mir eine andere Lösung - einfache 'list.forEach {print ($ 0!}} 'funktioniert (obwohl es natürlich aus anderen Gründen gefährlich ist) – matt

+0

Ja, aber list.forEach {print ($ 0)} stürzt auch ab. Die Notwendigkeit für flatMap hier ist für mich beängstigend. – Darko

2

Forced Unwrapping wie x:Int! ist eine gefährliche Codierung Stil, wenn Sie nicht ausschließen können Null. Gleiches gilt für var x:Int = list[i]!.

Dies funktioniert:

print("\nFor-in loop") 
for x in list { 
    print(x) 
} 

Hier können Sie x erlauben Null zu sein und später für null sicher überprüfen.

Nun zur Frage, warum Ihr Code:

Intern raschen list.generate() für die for-in-Schleife verwendet. Generatoren werden nicht beendet, was wahrscheinlich der Grund ist, warum Ihr Code kaputt geht.

+0

Aber das Problem ist, dass dies Optional (1), Optional (2) usw. ergibt, was das OP nicht will. – matt

+0

Sie haben Recht. Ich vermutete, dass das Drucken nur zum Debuggen ist und OP offensichtlich weiß, wie man es auspackt. Die interessantere Frage für mich war, warum es scheitert. –