Почему переменная цикла становится `nil` после цикла

objective-c cocoa nsdictionary fast-enumeration nsfastenumeration

158 просмотра

3 ответа

13375 Репутация автора

У меня есть:

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++)
{
    ...
}
Автор: meaning-matters Источник Размещён: 18.07.2016 08:15

Ответы (3)


5 плюса

2825 Репутация автора

Переменная, используемая в a 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

Надеюсь это поможет.

Автор: AnthoPak Размещён: 18.07.2016 08:23

-1 плюса

7016 Репутация автора

Это ноль после цикла, потому что 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;
}
Автор: Wyetro Размещён: 18.07.2016 08:44

7 плюса

43710 Репутация автора

Решение

Язык определяет, что переменная цикла будет иметь значение nil при выходе из цикла. Язык не утверждает, что переменная цикла будет иметь последнее значение, а наоборот.

За кулисами есть очень веская причина для этого. Быстрая итерация делает предположения о базовых данных. Например, когда вы перебираете изменяемый массив, массив не может быть изменен во время перебора. Быстрая итерация, помимо прочего, быстрая, потому что она не сохраняет и не освобождает переменную цикла. Вместо этого он опирается на базовый объект (например, массив) для хранения ссылки.

Но как только цикл завершается, этот объект больше не дает никаких гарантий. Массив может исчезнуть, или последний использовавшийся элемент массива может быть удален. Таким образом, компилятор должен либо сохранить переменную, либо установить ее в ноль. Установка на ноль быстрее.

Автор: gnasher729 Размещён: 18.07.2016 09:36
Вопросы из категории :
32x32