2012-11-27 16 views
11

Người ta nói trong tài liệu của apple: Một khối chữ (có nghĩa là,^{...}) là địa chỉ của một cấu trúc dữ liệu cục bộ ngăn xếp đại diện cho khối. Do đó, phạm vi cấu trúc dữ liệu ngăn xếp cục bộ, do đó bạn nên tránh các mẫu được hiển thị trong các ví dụ sau:Tôi không biết những gì khối của tôi nên tránh cho phạm vi chữ trong mục tiêu-c

void dontDoThis() { 

    void (^blockArray[3])(void); // an array of 3 block references 

    for (int i = 0; i < 3; ++i) { 

     blockArray[i] = ^{ printf("hello, %d\n", i); }; 

     // WRONG: The block literal scope is the "for" loop. 
    } 

    //for example I invoke the block here 
    blockArray[1](); 
    } 


void dontDoThisEither() { 

    void (^block)(void); 

    int i = random(): 

    if (i > 1000) { 

     block = ^{ printf("got i at: %d\n", i); }; 

     // WRONG: The block literal scope is the "then" clause. 

    } 

    // ... 

    } 

Tôi không biết các mẫu nên tránh. Có vẻ như tôi có thể gọi khối có cùng phạm vi chữ như định nghĩa khối, ví dụ như sau câu lệnh "if" hoặc "for". Bạn có thể giúp tôi giải thích nó không?

Ở đây nó là liên kết https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1

Trả lời

9

Tôi nghĩ rằng một tương tự để con trỏ là như sau.

void foo() { 
    int *block = NULL; 
    { 
    int a; 
    block = &a; 
    } 
    // `block`, even though defined here, points to 
    // an invalid memory address. 
} 

Nói chung, khối đen tự nó chỉ tồn tại trong khối nó được định nghĩa trong, vì vậy khi rời khỏi khối đó, biến mất chữ (như biến a đã làm trong ví dụ trên), và bạn đang trái với một con trỏ lơ lửng.

Vì lý do này, các khối thường được sao chép vào heap để sử dụng trong tương lai. Mã không phải ARC sử dụng block_copy và bạn bè. Sao chép vào heap cũng nắm bắt tất cả các biến có liên quan mà khối của bạn sử dụng (có thể tạo ra các chu kỳ lưu giữ).

Trong thực tế, tất cả điều này khá xa lánh khi sử dụng ARC, thuộc tính và lớp học. Bạn định nghĩa một thuộc tính copy trong lớp của bạn, và sau đó chỉ gán các khối cho nó. Nếu bạn để trình biên dịch tạo ra getter/setter, khối chữ của bạn sẽ tự động được sao chép vào heap.

@interface Bla : NSObject 
@property (nonatomic, copy) void (^blockProperty)(int i); 
@endf 

... 

Bla *bla = [[Bla alloc] init]; 
{ 
    bla.blockProperty = ^(int i) { printf("%d", i); }; 
} 
// bla.blockProperty now points to a heap copy of the block literal from above, 
// so it's not dangling. 
+0

Cảm ơn bạn. Và bạn có nghĩa là khối phải được khai báo như một thuộc tính được sao chép, thay vì một biến ngăn xếp trong phương thức? –

+0

hoặc tôi có thể khai báo một khối dưới dạng biến toàn cầu? Trên thực tế, nó nên được lưu trữ trong ngăn xếp cục bộ là tốt, nhìn thấy ở khắp mọi nơi. –

+0

OK! Cảm ơn nhiều. Câu lệnh ghép khối thích một giá trị số nguyên đáng kể, như là địa chỉ của một cấu trúc dữ liệu ngăn xếp cục bộ. –

0

Tôi đã đọc tài liệu của Apple về các khối và đã nghiên cứu thêm một chút về phần này. Có vẻ với tôi với ARC mã ví dụ thứ hai là hoàn toàn tốt đẹp. Tôi đã không thử ví dụ đầu tiên. Ý tưởng chung trong câu trả lời được chấp nhận là chính xác. Tuy nhiên, với ARC, khi bạn gán khối chữ (NSStackBlock) cho một biến cục bộ, khối được sao chép vào heap, và nếu bạn kiểm tra khối, bạn sẽ thấy nó thực sự là một NSMallocBlock. Tôi cũng đã tham chiếu blog này về chủ đề này https://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

Các vấn đề liên quan