enumerateObjectsUsingBlock的BOOL * stop参数是什么?


87

enumerateObjectsUsingBlock:最近,我为满足快速枚举的需求一直在使用很多东西,而且我很难理解BOOL *stop枚举块中的用法。

NSArray类引用状态

stop:对布尔值的引用。该块可以将值设置为,YES以停止对该数组的进一步处理。该stop参数是唯一的参数。您只能将此Boolean设置YES为Block内。

因此,当然可以在块中添加以下内容以停止枚举:

if (idx == [myArray indexOfObject:[myArray lastObject]]) {
    *stop = YES;
}

据我所知,不明确设置*stopYES不会产生任何负面影响。枚举似乎会自动在数组末尾停止。那么,使用代码*stop块真的有必要吗?

Answers:


156

stopBlock的参数允许您过早停止枚举。这等效break于普通for循环。如果要遍历数组中的每个对象,则可以忽略它。

for( id obj in arr ){
    if( [obj isContagious] ){
        break;    // Stop enumerating
    }

    if( ![obj isKindOfClass:[Perefrigia class]] ){
        continue;    // Skip this object
    }

    [obj immanetizeTheEschaton];
}

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if( [obj isContagious] ){
        *stop = YES;    // Stop enumerating
        return;
    }

    if( ![obj isKindOfClass:[Perefrigia class]] ){
        return;    // Skip this object
    }

    [obj immanentizeTheEschaton];
}];

那是一个out参数,因为它是对调用范围中变量的引用。它需要在您的Block内部进行设置,但要在中进行读取enumerateObjectsUsingBlock:,就像NSError通常将s从框架调用传递回代码一样。

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
    // N.B: This is probably not how this method is actually implemented!
    // It is just to demonstrate how the out parameter operates!

    NSUInteger idx = 0;
    for( id obj in self ){

        BOOL stop = NO;

        block(obj, idx++, &stop);

        if( stop ){
            break;
        }
    }
}

21
注意该stop标志是建议性的;例如,在并发情况下,枚举可能会继续进行一些不确定的迭代次数。也就是说,您不应__block在每次通过枚举时无条件地设置变量,并应将其用作stop用于提前终止的“最后一个”值。您应该始终将“否,使用此对象”与设置结合使用stop = YES;
bbum 2012年

@bbum,您能否澄清连续行为是否适用于并发枚举?虽然在这种情况下完全可以理解,但是没有记录,对于“串行”枚举来说,这将是令人惊讶的。
jscs

4
现在<rdar:// problem / 15015199>要求澄清,因为文档没有说任何一种方式,应该这样做。
bbum 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.