Đối số BOOL * stop cho enumerateObjectsUsingBlock: được sử dụng để làm gì?


87

enumerateObjectsUsingBlock:Gần đây, tôi đang sử dụng rất nhiều cho nhu cầu liệt kê nhanh của mình và tôi đang gặp khó khăn trong việc hiểu cách sử dụng BOOL *stoptrong khối liệt kê.

Các NSArraytrạng thái tham chiếu lớp

stop: Tham chiếu đến giá trị Boolean. Khối có thể đặt giá trị YESđể ngừng xử lý thêm mảng. Đối stopsố là đối số duy nhất. Bạn chỉ nên đặt Boolean này YEStrong Block.

Vì vậy, tất nhiên tôi có thể thêm phần sau vào khối của mình để dừng việc liệt kê:

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

Từ những gì tôi có thể nói, không thiết lập rõ ràng *stopđể YESkhông có bất kỳ tác dụng phụ tiêu cực nào. Việc liệt kê dường như tự động dừng lại ở cuối mảng. Vậy việc sử dụng có *stopthực sự cần thiết trong một khối không?

Câu trả lời:


156

Đối stopsố đối với Khối cho phép bạn dừng việc liệt kê sớm . Nó tương đương với breaktừ một forvòng lặp bình thường . Bạn có thể bỏ qua nó nếu bạn muốn xem qua mọi đối tượng trong mảng.

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

Đó là một tham số out vì nó là một tham chiếu đến một biến từ phạm vi gọi. Nó cần phải được đặt bên trong Block của bạn, nhưng đọc bên trong enumerateObjectsUsingBlock:, theo cùng một cách NSErrorthường được chuyển trở lại mã của bạn từ các lệnh gọi khung.

- (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
Lưu ý rằng stoplá cờ là cố vấn; ví dụ, việc liệt kê có thể tiếp tục đối với một số lần lặp không xác định trong trường hợp đồng thời. Tức là bạn không nên đặt một __blockbiến vô điều kiện trên mỗi lần đi qua phép liệt kê và mong đợi nó là giá trị "cuối cùng" khi sử dụng stopđể kết thúc sớm. Bạn nên luôn kết hợp "không, sử dụng đối tượng này" với cài đặt stop = YES;.
bbum

@bbum, bạn có thể làm rõ liệu hành vi tiếp tục chỉ áp dụng cho cách liệt kê đồng thời không? Mặc dù hoàn toàn có thể hiểu được trong trường hợp đó, nhưng nó không được ghi chép lại, và sẽ là một điều khá bất ngờ đối với kiểu liệt kê "nối tiếp".
jscs

4
<rdar: // problem / 15015199> bây giờ yêu cầu làm rõ vì tài liệu không nói cả hai cách và nó phải.
bbum
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.