2013-07-27 28 views
6

Mã sau đây là từ mã mẫu LazyTableImages do Apple cung cấp (source here).Tự chụp trong khối (giữ lại chu kỳ), không phải lúc nào?

Trong khối hoàn thành, chúng có tham chiếu đến bản thân sẽ gây ra chu kỳ giữ lại ... Nhưng tôi không nhận được cảnh báo về điều này trong Xcode trong khi ở mã tương tự của tôi.

Điều này có đúng không?

Có lẽ tôi đang thiếu một sự tinh tế về điều này.

- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath 
{ 
    IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath]; 
    if (iconDownloader == nil) 
    { 
     iconDownloader = [[IconDownloader alloc] init]; 
     iconDownloader.appRecord = appRecord; 
     [iconDownloader setCompletionHandler:^{ 

      UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; 

      // Display the newly loaded image 
      cell.imageView.image = appRecord.appIcon; 

      // Remove the IconDownloader from the in progress list. 
      // This will result in it being deallocated. 
      [self.imageDownloadsInProgress removeObjectForKey:indexPath]; 

     }]; 
     [self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath]; 
     [iconDownloader startDownload]; 
    } 
} 
+1

có thể trùng lặp của [Có thể truyền \ [self anyFunction \] trong các khối không có đối tượng yếu \ _ \ _ (iOS 5 + ARC)] (http://stackoverflow.com/questions/9003600/possible-to-pass- self-anyfunction-in-blocks-without-weak-object-ios-5-arc), Xin lỗi Daniel :) – Abizern

+0

Bạn đang nói không có cảnh báo vì có nhiều hơn một cấp cho chu kỳ, @Abizern? –

+0

Không có cảnh báo vì không có chu kỳ lưu giữ. – Abizern

Trả lời

4

Chu kỳ lưu giữ mà bạn cho rằng bạn đang thấy là do đối tượng giữ trình tải xuống trong từ điển.

Đúng là có tham chiếu mạnh mẽ đến tự trong khối, nhưng miễn là trình xử lý hoàn thành luôn chạy, trình tải xuống sẽ bị xóa khỏi từ điển. Và cuối cùng từ điển này sẽ trống rỗng, điều đó có nghĩa là sẽ không có đối tượng nào giữ lại bản thân, và do đó không có chu kỳ giữ lại.

+2

Trình biên dịch sử dụng quy ước đặt tên để quyết định thời tiết để cảnh báo về một chu trình giữ lại tiềm năng hay không, so sánh [Clang - Blocks giữ lại chu kỳ từ quy ước đặt tên?] (Http://stackoverflow.com/questions/15535899/clang-blocks-retain- quy ước-từ-đặt tên). –

0

self không có con trỏ mạnh đến iconDownloader. Nó được tạo ra và scoped chỉ để phương pháp này:

IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath]; 

Nếu iconDownloader là một tính chất mạnh mẽ (self.iconDownloader) sau đó Xcode sẽ phát hiện một chu kỳ tài liệu tham khảo mạnh mẽ.

+0

Đối tượng 'iconDownloader' dường như được sở hữu bởi' imageDownloadsInProgress', có lẽ thuộc sở hữu của 'self'; nếu 'iconDownloader' cũng sở hữu khối hoàn thành của nó, thì, vâng, đây là một chu kỳ giữ vững. –

+0

Bắt tốt. Tôi nghĩ rằng có một chu kỳ giữ lại ở đây, nhưng vì nó đang trải qua một NSDictionary, Xcode không tạo ra cảnh báo. –

+0

Trên một lưu ý phụ, sử dụng lớp 'IconDownloader' là một công thức cho thảm họa nếu dữ liệu của bạn thay đổi thường xuyên. Bạn không nên sử dụng 'indexPath' để xác định vị trí đặt hình ảnh của bạn sau khi tải xuống nếu có bất kỳ cơ hội nào dữ liệu của bạn có thể được đặt ở một đường dẫn chỉ mục khác bất cứ khi nào hình ảnh được tải xuống xong. –

0

Tự chụp bản thân không có chu kỳ lưu giữ. Nó là một tham chiếu duy nhất. Một tham chiếu không thể tạo chu trình. Các antipattern thông thường là, bổ sung thêm một tham chiếu đến khối được lưu trữ trong một tài sản mạnh mẽ của bản thân. Hơn có hai tham chiếu xây dựng một chu kỳ.

0

Không có cảnh báo vì trình biên dịch chưa có khả năng phát hiện tất cả các chu kỳ lưu giữ có thể có.

Ví dụ:

- (void)foo 
{ 
    _block =^{ [self done]; }; // Warning: Possible retain cycle 

    DSGenericBlock foo =^{ [self done] }; 
    _block = foo; // No warning. 
} 

Nếu bạn đã gán khối trực tiếp đến một biến thể hiện của "tự", bạn sẽ nhận được "có thể duy trì chu kỳ" cảnh báo. Thay vào đó, khối được gán cho một đối tượng khác, mà sau đó được giữ lại bởi chính bản thân, do đó trình biên dịch không phát hiện chu kỳ (mặc dù chu trình tồn tại).

+1

Không có cảnh báo vì không có chu kỳ giữ lại. – Abizern

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