调试运行到具有保留周期的块

Debug runs into block with retain cycle

我有问题,我已经知道不能那样使用,但我想在这里问的只是解释,而不是如何解决。请注意。

我正在使用 UIImageView+AFNetworking,我这样调用服务:

UIImageView* imageView = [[UIImageView alloc]init];
    [imageView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image) {
        NSLog(@"In here.");
    } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
        completionBlock(nil, error);
    }];

这种情况下,它不会运行变成NSLog(@"In here.")。我们可以看到 imageView 被释放了。但是当我这样使用时:

UIImageView* imageView = [[UIImageView alloc]init];
    [imageView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image) {
        NSLog(@"In here.");
        imageView.image = image; /* I know this will make retain cycle. but don't care, just need explanation why? */
    } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
        completionBlock(nil, error);
    }];

现在调试运行进入NSLog(@"In here.")imageView有些显示仍然保留,请告诉我为什么?

注意:请不要给出解决方法和正确的使用方法,只解释为什么?

=====

感谢大家的支持,我终于明白了。

在第一段代码中,imageView会在setImageWithURLRequest的末尾release,所以它不会调用success块,这就是为什么NSLog(@"In here.") 未被调用。

在第二个中,通过设置imageView.image = image,将进行保留循环,这意味着imageView现在持有对success块的强引用,然后在块内部,我正在调用 imageView 来使用,所以现在 success 块持有对 imageView 的强引用,这使得保留循环现在 imageView 不会被释放。因此,进入 NSLog(@"In here.").

我假设您的代码看起来像这样并在 ARC

下运行
- (void) yourMethod {
    UIImageView* imageView = [[UIImageView alloc]init];
    [imageView setImageWithURLRequest:request placeholderImage:nil success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image) {
        NSLog(@"In here.");
    } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
        completionBlock(nil, error);
    }];
}

在 ARC 下,当控制到达 yourMethod 的末尾时,imageView 被释放。

通过添加:

imageView.image = image;

success 块保留对 imageView 的引用,这就是为什么您会看到 "In here" 消息(imageView 将在 success 阻止执行)。尝试将 imageView 声明为 class 的强 属性,您应该得到 "In here" 而无需将此行添加到 success 块。