Почему переменная цикла становится `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;
}
Другие вопросы по тегам