5

Tôi nghĩ rằng tôi hiểu từ khóa mạnh và yếu, nhưng tôi không hiểu cách sử dụng từ khóa trong mã bên dưới. Mã này là từ SDWebImage bởi Olivier Poitrey có sẵn trên github. Tôi hiểu các từ khóa mạnh và yếu như được mô tả ở đây: Explanation of strong and weak storage in iOS5Giải thích __weak và __strong lý do sử dụng trong mã SDWebImage

Mã bên dưới sử dụng các từ khóa __weak và __strong theo cách tò mò với tôi. Nó không phải là một mối quan hệ cha mẹ hoặc mẫu đại biểu như tôi đã từng thấy yếu được sử dụng. Tuy nhiên, tôi chắc chắn rằng đây là một mẫu được sử dụng thường xuyên, như tôi đã nhìn thấy nó trước trong mã khác. Nó đặt một tham chiếu __weak trước một khối chạy trên một luồng khác. Sau đó, trong khối, nó đặt tham chiếu yếu đến tham chiếu mạnh.

Tôi chắc chắn rằng mã tốt và thanh lịch này, vì vậy tôi đang cố gắng hiểu nó. Nếu "tự" chấm dứt tồn tại trước khi khối chạy, thì tham chiếu tự yếu sẽ không ra. Khi khối chạy, tham chiếu mạnh sẽ được đặt thành 0. Vì vậy, nó sẽ biết để giết phần còn lại của hoạt động kể từ khi tự không tồn tại nữa. Tôi đã nhận được quyền này?

Bây giờ, điều gì sẽ xảy ra nếu chúng tôi không sử dụng từ khóa __weak và __strong? Điều gì xảy ra nếu chúng ta chỉ kiểm tra bên trong khối cho dù tự == không. Liệu "bản thân" có bao giờ là không vì khối sao chép toàn bộ cây?

Ai đó có thể giúp làm sáng tỏ đoạn mã tuyệt vời này? Ai đó có thể xác minh hoặc từ chối giả thuyết của tôi?

- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletedBlock)completedBlock; 
{ 
    [self cancelCurrentImageLoad]; 

    self.image = placeholder; 

    if (url) 
    { 
     __weak UIImageView *wself = self; 
     id<SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished) 
     { 
      __strong UIImageView *sself = wself; 
      if (!sself) return; 
      if (image) 
      { 
       sself.image = image; 
       [sself setNeedsLayout]; 
      } 
      if (completedBlock && finished) 
      { 
       completedBlock(image, error, cacheType); 
      } 
     }]; 
     objc_setAssociatedObject(self, &operationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
    } 
} 

Trả lời

7

Phương thức downloadWithUrl: có thể mất nhiều thời gian. Trong thời gian đó, người dùng có thể quyết định điều hướng đi, loại bỏ nhu cầu đối tượng SDWebImage. Để tạo thuận lợi cho việc dọn dẹp sớm đối tượng, tham chiếu bên ngoài self yếu. Bằng cách này, downloadWithUrl sẽ không ngăn không cho SDWebImage bị phân phối lại.

Tất nhiên, nếu bạn thực sự muốn làm việc với self, bạn cần tham chiếu mạnh mẽ. Vì vậy, khối hoàn thành của downloadWithUrl lấy một tham chiếu mạnh mẽ đến self. Nếu đối tượng này biến mất trong thời gian này, sself sẽ là nil. Nếu không, nó sẽ là một tham chiếu mạnh hợp lệ, chỉ ra rằng đối tượng SDWebImage vẫn còn xung quanh, và đối tượng sẽ kết thúc công việc của mình tại thời điểm này.

+0

Một câu trả lời tuyệt vời khác. Cảm ơn nneonneo. –

+1

Nó không chỉ là "Để tạo điều kiện dọn dẹp sớm đối tượng". Nó tạo điều kiện làm sạch đối tượng ở tất cả - nếu không sẽ có một chu kỳ giữ lại - 'self' giữ lại' hoạt động' thông qua tham chiếu liên kết. 'hoạt động' giữ lại khối. Nếu khối được giữ lại 'self', nó sẽ là một chu kỳ. – newacct

3

Tôi chắc chắn rằng mã tốt và thanh lịch này, vì vậy tôi đang cố gắng hiểu nó. Nếu "tự" chấm dứt tồn tại trước khi khối chạy, thì tham chiếu tự yếu sẽ không ra. Khi khối chạy, tham chiếu mạnh sẽ được đặt thành 0. Vì vậy, nó sẽ biết để giết phần còn lại của hoạt động kể từ khi tự không tồn tại nữa. Tôi đã nhận được quyền này?

Không, bạn đang suy nghĩ kỹ về điều này một chút. Bộ định mức lưu trữ __weak chỉ là: một vòng loại. Các đối tượng là __weak rõ ràng không được giải quyết, nhưng chúng không chỉ được đặt tự động thành nil nếu được gán từ một biến mạnh. Trong thực tế, điều đó sẽ đánh bại mục đích của một biến yếu!

Bây giờ, điều gì sẽ xảy ra nếu chúng tôi không sử dụng từ khóa __weak và __strong? Điều gì xảy ra nếu chúng ta chỉ kiểm tra bên trong khối cho dù tự == không. Liệu "bản thân" có bao giờ là không vì khối sao chép toàn bộ cây?

Việc kiểm tra thực sự không cần thiết vì thời gian chạy giải quyết thư từ 0 đến 0 (tuy nhiên, điều này có thể quan trọng đối với việc triển khai sau này, ai biết).Bạn có mặt tại chỗ với cái này: không có điệu nhảy "yếu đến mạnh" đó, thì bản thân sẽ được giữ lại bởi khối, với khả năng tạo ra một chu kỳ giữ lại khá khó chịu. Đó là nơi tôi có thể bắt đầu kết hợp tất cả điều này với nhau:

Vì chúng tôi không muốn khối giữ nguyên biến số của chúng tôi, nhưng chúng tôi cũng muốn nó nằm trong phạm vi khối nên không có gì lạ xảy ra, tự được chỉ định đến một con trỏ yếu. Khi khối xuất hiện trên con trỏ yếu của chúng ta, nó không được phép giữ lại nó, vì vậy số tham chiếu của bản thân vẫn giữ nguyên, sau đó một lần bên trong khối, chúng ta quay trở lại một biến tự mạnh để cái yếu được giải phóng, và không phải lo lắng về nó nữa. Thực tế, điều này có nghĩa là chúng ta có một sự đảm bảo vững chắc rằng bản thân là giá trị hoặc số không trong suốt quá trình thực thi khối. Khá gọn gàng, huh?

+0

Đoạn cuối cùng của bạn rất hữu ích. Cảm ơn CodaFi. –

+0

Tôi không hiểu cụm từ này: "... chúng ta quay trở lại với một biến tự mạnh để cái yếu được giải phóng". Có phải chính mình ở đó để tạo ra một tham chiếu mạnh mẽ để chắc chắn rằng bản thân sẽ không được phát hành ở giữa thực hiện các khối của chủ đề khác? – Boon

+1

Sắp xếp. Nếu bạn không gán lại cho một biến mạnh trong khối, nó có thể được giải phóng từ bên dưới chúng ta và đặt thành 0 ở giữa khối thực thi. Bằng cách gán cho bạn mạnh mẽ, bạn đảm bảo rằng bản thân không phải là không hoặc không trong suốt toàn bộ thời gian thực hiện của khối. – CodaFi

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