I have:
NSDictionary* server;
for (server in self.servers)
{
if (<some criterium>)
{
break;
}
}
// If the criterium was never true, I want to use the last item in the
// the array. But turns out that `server` is `nil`.
The loop block never changes server
.
servers
is an NSMutableArray
with dictionaries, a property that's not changed during the loop.
Why does server
have the value nil
after the loop has ended?
Was the first time I used such a variable after the loop. Without thinking too much, I assumed it would work like (in the old C days):
int i;
for (i = 0; i < n; i++)
{
...
}
The language defines that the loop variable will be set to nil when the loop exits. The language doesn't state that the loop variable will have the last value, quite the opposite.
Behind the scenes, there is a very good reason for that. Fast iteration makes assumptions about the underlying data. For example, when you iterate over a mutable array, the array may not be modified while you iterate. Fast iteration is fast, among other things, because it doesn't retain and release the loop variable. Instead it relies on the underlying object (for example an array) to hold a reference.
But once the loop exits, that underlying object gives no guarantees anymore. The array could go away, or the array element that was last used might get deleted. So the compiler either must retain the variable, or set it to nil. Setting to nil is quicker.