อาร์กิวเมนต์ BOOL * stop สำหรับ enumerateObjectsUsingBlock: ใช้สำหรับอะไร


87

ช่วงนี้ฉันใช้enumerateObjectsUsingBlock:งานจำนวนมากสำหรับความต้องการการแจงนับอย่างรวดเร็วและฉันมีปัญหาในการทำความเข้าใจการใช้งานBOOL *stopในบล็อกการแจงนับ

NSArrayรัฐอ้างอิงระดับ

stop: การอ้างอิงถึงค่าบูลีน บล็อกสามารถกำหนดค่าYESเพื่อหยุดการประมวลผลอาร์เรย์เพิ่มเติมได้ stopอาร์กิวเมนต์เป็นข้อโต้แย้งออกเท่านั้น คุณควรตั้งค่าบูลีนนี้เป็นYESภายในบล็อกเท่านั้น

ดังนั้นแน่นอนฉันสามารถเพิ่มสิ่งต่อไปนี้ในบล็อกของฉันเพื่อหยุดการแจงนับ:

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

จากสิ่งที่ฉันสามารถบอกได้การไม่ตั้งค่าอย่างชัดเจน*stopให้YESไม่มีผลข้างเคียงเชิงลบใด ๆ การแจงนับดูเหมือนจะหยุดตัวเองโดยอัตโนมัติเมื่อสิ้นสุดอาร์เรย์ ดังนั้นการใช้จึง*stopจำเป็นจริงๆในบล็อก?

คำตอบ:


156

stopอาร์กิวเมนต์บล็อกช่วยให้คุณสามารถที่จะหยุดนับก่อนเวลาอันควร มันเทียบเท่า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 เนื่องจากเป็นการอ้างอิงถึงตัวแปรจากขอบเขตการเรียกใช้ จำเป็นต้องตั้งค่าไว้ในบล็อกของคุณ แต่อ่านภายในenumerateObjectsUsingBlock:วิธีเดียวกับNSErrorที่ส่งกลับไปยังรหัสของคุณจากการเรียกเฟรมเวิร์ก

- (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

@bbum คุณสามารถชี้แจงได้หรือไม่ว่าพฤติกรรมต่อเนื่องใช้เฉพาะกับการแจงนับพร้อมกันเท่านั้น แม้ว่าจะเข้าใจได้อย่างสมบูรณ์แบบในกรณีนั้น แต่ก็ไม่ได้รับการจัดทำเป็นเอกสารและจะเป็นการกัดที่น่าแปลกใจสำหรับการแจงนับ "อนุกรม"
jscs

4
ตอนนี้ <rdar: // problem / 15015199> ขอคำชี้แจงเนื่องจากเอกสารไม่ได้ระบุไว้อย่างใดอย่างหนึ่งและควร
bbum
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.