Reputation: 22996
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++)
{
...
}
Upvotes: 4
Views: 299
Reputation: 4391
The variable used in a for-loop
will always be nil
when loop ends (except if the loop is broken with break
statement, as pointed by @rmaddy).
Another way for your loop which will avoid misunderstanding is :
for (NSDictionary* server in self.servers)
{
//... server is not nil
}
//here server doesn't exist (out of scope)
If you want to save a value of self.servers in a var outside of the loop you'll have to do this :
NSDictionary* serverSave;
for (NSDictionary* server in self.servers)
{
serverSave = server;
}
//here you can use serverSave, which will contain the last value of self.servers
Hope this helps.
Upvotes: 5
Reputation: 8588
It's nil after the loop because Objective-C with ARC nills it (see Value of loop variable after "for in" loop in Objective C).
Thus when you get to the end of:
NSDictionary* server; // server is nil here
for (server in self.servers)
{
... // Does not set server to nil.
}
server
will be nil.
If you are looking for a certain value you can do this:
NSDictionary *dict;
for (NSDictionary* server in self.servers)
{
if (server == whatever you want){
dict = server;
break;
}
}
Or to just get the last value:
NSDictionary *dict;
for (NSDictionary* server in self.servers)
{
dict = server;
}
Upvotes: -1
Reputation: 52632
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.
Upvotes: 7