9

Tôi đã có một số mã với một chu trình tham chiếu rõ ràng trong một khối ivar. Các mã sau đây gây ra một chu kỳ tài liệu tham khảo và dealloc không bao giờ được gọi là:__block chu trình tự tham chiếu trong khối ivar trong ARC

__block MyViewController *blockSelf = self; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockSelf.delegate loginDidFinish]; 
     });    
    } 
}; 

Tuy nhiên, nếu tôi có thể tạo một biến khác __block để giữ một tham chiếu đến đại biểu của tôi cho phạm vi của khối để chụp, chu kỳ tài liệu tham khảo sẽ biến mất:

__block id <MyViewControllerDelegate> blockDelegate = self.delegate; 

loggedInCallback = ^(BOOL success, NSError *error){ 
    if (success) 
    { 
     double delayInSeconds = 1.0; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, dispatch_get_main_queue(), ^(void) 
     { 
      [blockDelegate loginDidFinish]; 
     });    
    } 
}; 

Chỉ muốn hiểu những gì đang xảy ra ở đây.

Trả lời

16

Tôi sẽ giả sử bạn đang sử dụng ARC tại đây. Trước ARC, ví dụ đầu tiên của bạn sẽ hoạt động tốt. Với ARC ngữ nghĩa của __block đã thay đổi. __block khai báo hiện được ghi lại mạnh mẽ, thay vì yếu. Thay thế __block bằng __weak trong mẫu đầu tiên của bạn và tất cả sẽ hoạt động như mong đợi.

Đối với ví dụ thứ hai hoạt động, bạn đang tạo tham chiếu mạnh mẽ cho người được ủy quyền, nhưng tài liệu đó không có tham chiếu về đối tượng của bạn. Do đó không có chu kỳ và mọi người đều hạnh phúc.

tôi khuyên bạn nên đọc bài viết Mike Ash về tình hình biến được giới thiệu với ARC, đặc biệt là xung quanh chụp khối và __weakhttp://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

+0

Perfect, cảm ơn! Tôi đã cập nhật tiêu đề câu hỏi của mình để mang tính mô tả hơn. –

+1

Tôi đang nhắm mục tiêu iOS 4.3, vì vậy tôi đã phải sử dụng '' __unsafe_unretained'' để thay thế, nhưng nó hoạt động, cảm ơn! –

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