I try to add 1 to i in a loop for in a specific moment? When I do this, it comes to the "normal" value instantly at the begining of the loop.
for var i in (0..<10)
{
if (i == 2)
{
i += 1
}
}
EDIT:
Concret code:
for var i in (0..<models.count)
{
if (i > 0 && models[i].label1 == models[i-1].label1)
{
models[i-1].slots.append(contentsOf: models[i].slots)
models.remove(at: i)
i -= 1
}
}
3
Answers
The for loop sets the value of
i
each time through.So,
Inside your
if (i == 2)
block, you change the value ofi
but then the for loop changes it right back to the next value in the enumeration of 0 to 9.The debug output from the above code will look like this:
To make it more obvious, change
i += 1
toi += 4
Output:
Edit – for a little more clarification…
From the Swift Docs:
Both of these loops:
will output this:
and this loop:
will output this:
because the for-in loop is iterating over the sequence.
In either case, if we try to modify
i
inside the loop, we’ll see this in Xcode:If we change
i
to a var:we can compile and run the code, but… each time through the loop
i
will be assigned the next value in the iteration, and we’ll get this:As
Duncan C
explained, if we want to actually modifyi
, the proper thing to do is use awhile
loop.So… why can we do this in other languages (such as Objective-C):
and get this output:
and the loop exits?
That’s because this:
is a more concise yet functionally equivalent way of writing this:
The Swift
For-In
loop is much more similar to the Objective-CFor-In Fast Enumeration
loop:outputs:
and, if we try to modify
n
inside the loop:so we make it
__strong
:and the output is – as you might guess:
Hope that helps a bit.
In for loops in Swift, the variable (
i
) is treated as a let constant, and you cannot mutate it inside the loop.That seems right. Being able to mutate a loop variable inside the loop can lead to all sorts of unexpected side-effects.
You can use a while loop to get the same effect:
The following works:
This code throws a compiler error:
The problem is caused because the
i
is scoped to the block of the loop. Each time round you actually get a newi
.There are three solutions.
The first is to use a
while
loop as per Duncan C’s answer.The second is to maintain a separate index and still use a for loop, but that’s really just the same as the first one
The best answer IMO is to count downwards from the end.
Of course, reversing a list of numbers gets expensive for long lists, so you might consider using stride