ObjC:局部变量似乎在函数调用中保持其值

时间:2013-10-09 15:10:21

标签: objective-c automatic-ref-counting scope objective-c-blocks enumeration

我偶然发现了我写的一个调查员中的一个奇怪的错误:

// typedef for reference
typedef void (^OGWEntityEnumerationBlock)(OGWEntity* entity, BOOL* stop);


-(void) enumerateEntitiesInCategory:(const OGWEntityCategory*)category 
                         usingBlock:(OGWEntityEnumerationBlock)block
{
    BOOL stop;
    NSArray* entitiesInCategory = [_cagetorizedEntities objectForKey:category];

    for (OGWEntity* entity in [entitiesInCategory reverseObjectEnumerator])
    {
        block(entity, &stop);

        if (stop)
        {
            break;
        }
    }
}

首次使用enumerateEntitiesInCategory:usingBlock:可以正常使用。最终,调用者找到它正在搜索的实体,并将*stop参数设置为YES

第一次迭代后,enumerateEntitiesInCategory:usingBlock:的下一次使用会立即退出。经过仔细检查,只要上一次迭代将stop参数设置为YES,YES就会初始化为*stop。我必须用NO有目的地初始化stop变量来解决这个问题。

这怎么可能?我知道停止变量的地址(可能是偶然的)在调用之间可能保持不变,这可以解释那里的“旧”值。但我认为ARC确保未初始化的类型分别设置为0 nil,所以不应该在每次调用函数时将BOOL设置为NO?

有趣的是,如果我使用__block BOOL stop;,则根据调试器将始终初始化为YES,即使在第一次(也可能是偶然的,取决于任何未初始化的值是在那个地址)。

这似乎表明我可能错误地认为未初始化的变量是零和ARC - 也许ARC真的只关心用nil初始化对象类型但不关心整数类型?或者这仅适用于ivars而非局部变量?

1 个答案:

答案 0 :(得分:6)

只有指向Objective-C对象的指针通过ARC初始化为nil (以及对象的所有实例变量),但一般不是局部变量。 所以你必须用

初始化布尔变量
BOOL stop = NO;