For-in loop goes too far and finds "nil" during deployment

It looks like the next Swift for-in loop is trying to go through more elements than in the array.

For example, this 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) } 

Gets this output:

 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 

Something must be missing for me. Should list.count be the number of elements the for-in loop is trying to implement?

Not pictured above, the for-in loop works as expected if you use [Int] instead of [Int?] Without unpacking.

I am on Swift version 2.1.1.

+5
source share
2 answers

Basically, you did something that you do not need to do, and thus, you came across what was probably a compiler error (because the compiler did not stop you). Very nice!

Now the decision. You are obviously trying to deploy using Int! . For safe deployment, use the 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 } 

Another way (same result):

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

Forced decoupling, for example x:Int! is a dangerous coding style when you cannot exclude nil. The same is true for var x:Int = list[i]! .

It works:

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

Here you allow x to be nil and can safely check for zero later.

Now to the question why your code breaks:

Internally, swift uses list.generate() for a for-in loop. Generators are null terminated, which is probably the reason your code breaks.

+2
source

Source: https://habr.com/ru/post/1245870/


All Articles