Почему переменная цикла становится `nil` после цикла
Я имею:
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`.
Блок цикла никогда не меняется server
,
servers
является NSMutableArray
со словарями свойство, которое не изменяется во время цикла.
Почему server
иметь значение nil
после окончания цикла?
Был первый раз, когда я использовал такую переменную после цикла. Не думая слишком много, я предположил, что это будет работать так (в старые времена C):
int i;
for (i = 0; i < n; i++)
{
...
}
3 ответа
Язык определяет, что переменная цикла будет иметь значение nil при выходе из цикла. Язык не утверждает, что переменная цикла будет иметь последнее значение, а наоборот.
За кулисами есть очень веская причина для этого. Быстрая итерация делает предположения о базовых данных. Например, когда вы выполняете итерацию по изменяемому массиву, массив может не изменяться во время итерации. Быстрая итерация, помимо прочего, быстрая, потому что она не сохраняет и не освобождает переменную цикла. Вместо этого он опирается на базовый объект (например, массив) для хранения ссылки.
Но как только цикл завершается, этот базовый объект больше не дает никаких гарантий. Массив может исчезнуть, или последний использованный элемент массива может быть удален. Поэтому компилятор должен либо сохранить переменную, либо установить ее в ноль. Установка на ноль быстрее.
Переменная, используемая в for-loop
всегда будет nil
когда цикл заканчивается (кроме случаев, когда цикл прерывается break
заявление, как указано @rmaddy).
Другой способ для вашего цикла, который поможет избежать недоразумений:
for (NSDictionary* server in self.servers)
{
//... server is not nil
}
//here server doesn't exist (out of scope)
Если вы хотите сохранить значение self.servers в переменной за пределами цикла, вам нужно сделать это:
NSDictionary* serverSave;
for (NSDictionary* server in self.servers)
{
serverSave = server;
}
//here you can use serverSave, which will contain the last value of self.servers
Надеюсь это поможет.
Это ноль после цикла, потому что Objective-C с ARC обнуляет его (см. Значение переменной цикла после цикла "for in" в Objective C).
Таким образом, когда вы доберетесь до конца:
NSDictionary* server; // server is nil here
for (server in self.servers)
{
... // Does not set server to nil.
}
server
будет ноль.
Если вы ищете определенное значение, вы можете сделать это:
NSDictionary *dict;
for (NSDictionary* server in self.servers)
{
if (server == whatever you want){
dict = server;
break;
}
}
Или просто получить последнее значение:
NSDictionary *dict;
for (NSDictionary* server in self.servers)
{
dict = server;
}