【问题标题】:Why in SDWebImage "strong reference to UIImageView might cause a crash in the nested block"?为什么在 SDWebImage 中“对 UIImageView 的强引用可能会导致嵌套块崩溃”?
【发布时间】:2016-05-24 22:09:58
【问题描述】:

我正在使用旧版本的 SDWebImage,但收到如下崩溃:

0   libobjc.A.dylib                     0x000000019671bbd0 objc_msgSend + 16
1   UIKit                               0x0000000189932eac -[UIView(Rendering) contentMode] + 316
2   UIKit                               0x00000001899320e0 -[UIImageView _canDrawContent] + 144
3   UIKit                               0x0000000189932bac -[UIImageView _updateState] + 36
4   UIKit                               0x0000000189932b6c +[UIView(Animation) performWithoutAnimation:] + 88
5   UIKit                               0x0000000189c6b340 -[UIImageView _updateImageViewForOldImage:newImage:] + 452
6   UIKit                               0x0000000189932590 -[UIImageView setImage:] + 320
7   xxxx                                0x0000000100927adc __85-[UIImageView(WebCache) setImageWithURL:placeholderImage:options:progress:completed:]_block_invoke + 100

发生崩溃的区块是:

        __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 setNeedsDisplay];
                                                 [sself setNeedsLayout];
                                             }
                                             if (completedBlock && finished)
                                             {
                                                 completedBlock(image, error, cacheType);
                                             }
                                         }];

然后我找到了 SDWebImage 的修复,提交评论是:

移除了导致嵌套块崩溃的 UIImageView 的强引用

这里是commit。唯一的变化是删除块中UIImageView 的强引用。

在块中使用强引用来保持一致性被广泛使用,但是为什么SDWebImage会有这个变化。为什么这可能会导致崩溃?如果UIImageView 会导致崩溃,还有什么?

【问题讨论】:

  • 我的猜测是 IV 已从视图层次结构中删除,或者以其他方式置于无法在不崩溃的情况下绘制图像的状态。删除强引用会阻止 IV 在进入此无效状态后生效。
  • @Avi 听起来很合理。但是还是要一个准确的解释,如果UIImageView有这种问题,其他的呢?
  • 异常信息是什么,是否与自动布局有关?
  • @Wain 异常类型是 SIGSEGV。异常代码是:SEGV_MAPERR

标签: ios objective-c uiimageview sdwebimage


【解决方案1】:

该修复可以解决的问题是视图移除和/或销毁期间的竞争条件,其中内部渲染缓冲区正在被释放,但可以及时应用保留以防止释放。然后,如果有什么东西触发了写入那些现在消失的缓冲区,你就会得到那个分段错误。

理论上,在直接访问原始指针并且它们的破坏没有得到充分保护的任何地方都可能遇到这个问题。实际上,除了基于 UIImage 的 API 之外,UIKit 级别的代码不太可能在任何地方遇到它,我想这将是一个相当深奥的竞争条件,在视图拆卸开始之前小心取消所有异步更新应该完全消除;无论如何,您应该这样做以避免不必要的工作。

【讨论】:

  • 感谢您的回答,我们应该谨慎使用基于 UIImage 的 API 的强引用。
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2021-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多