为什么循环变量在循环后变为`nil`

时间:2016-07-18 20:15:22

标签: objective-c cocoa nsdictionary fast-enumeration nsfastenumeration

我有:

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 个答案:

答案 0 :(得分:7)

语言定义循环退出时循环变量将设置为nil。该语言并未声明循环变量将具有最后一个值,恰恰相反。

在幕后,有一个很好的理由。快速迭代对底层数据做出假设。例如,当您遍历可变数组时,迭代时可能不会修改该数组。除其他外,快速迭代很快,因为它不会保留和释放循环变量。相反,它依赖于底层对象(例如数组)来保存引用。

但是一旦循环退出,那个底层对象就不再提供任何保证了。数组可能会消失,或者上次使用的数组元素可能会被删除。因此编译器必须保留变量,或将其设置为nil。设置为nil更快。

答案 1 :(得分:5)

当循环结束时,for-loop中使用的变量将始终为nil(除非循环被break语句破坏,如@rmaddy指出的那样。

你的循环的另一种避免误解的方法是:

for (NSDictionary* server in self.servers)
{
    //... server is not nil
}
//here server doesn't exist (out of scope)

如果你想在循环外的var中保存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

希望这有帮助。

答案 2 :(得分:-1)

在循环之后它是零,因为带有ARC的Objective-C将它填满(参见docs)。

因此,当你到达结束时:

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;
}