iOS解决方案只有在尚未使用SDWebImage在内存中缓存时才能使用动画加载图像

NKo*_*kov 3 caching uiimageview ios sdwebimage

我几天来一直在努力解决这个问题.以前我使用AFNetworking类来加载和缓存图像,但它没有在它的回调中提供缓存类型.所以我曾经在每个控制器中跟踪哪些图像已经加载.我浏览了SDWebImage,它提供了我正在寻找的东西 - SDImageCacheType.

现在我试图想出一个易于使用(希望是一个单行)的解决方案来加载表格和集合视图中的图像,如果它们被下载或来自磁盘缓存.基本上这些任务需要一些时间才能获得实际图像,当内存缓存瞬间提供图像时,因此当图像来自内存时不需要动画.

我想出了这个UIImageView类别,我希望有更有经验的人提供一些反馈.它确实似乎按预期工作.我不确定我是在这里重新发明轮子,否则这种做法在某些情况下可能会适得其反.

概述是做两件事.在完成块中,当图像准备好使用时,它根据已使用的缓存级别设置动画持续时间.第二个想法是可重复使用的单元机制,imageView在相关对象的帮助下跟踪加载操作,如果有正在进行的任务则取消它.AFNetworking解决方案不需要这样做,因为当您设置新的解决方案时,它会默认取消正在进行的图像加载.我不喜欢这样的事实,即操作被保留,它不应该被保留,但是关联的对象不提供一种__weak类型的引用.OBJC_ASSOCIATION_ASSIGNkey似乎会产生对象__unsafe_unretained并导致访问崩溃.

任何意见,将不胜感激.

static char kOperationKey;

- (id <SDWebImageOperation>)scrb_setImageAnimatedWithURL:(NSURL *)url {

    id <SDWebImageOperation> lastOperation = objc_getAssociatedObject(self, &kOperationKey);

    if (lastOperation) {
        [lastOperation cancel];
    }

    id <SDWebImageOperation> operation = [[SDWebImageManager sharedManager] downloadImageWithURL:url options:SDWebImageRetryFailed progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {

        if (finished && image) {

            BOOL animated = NO;

            if (cacheType == SDImageCacheTypeDisk || cacheType == SDImageCacheTypeNone) {
                animated = YES;
            }

            if (animated) {

                [UIView transitionWithView:self duration:ANIMATION_DURATION options:UIViewAnimationOptionTransitionCrossDissolve animations:^{

                    self.image = image;

                } completion:nil];

            } else {

                self.image = image;

            }

        }
    }];

    objc_setAssociatedObject(self, &kOperationKey, operation, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    return operation;

    }
Run Code Online (Sandbox Code Playgroud)

--- UPDATE ---

@ n00neimp0rtant的帮助下,我将我的类别更改为:

- (void)scrb_setImageAnimatedWithURL:(NSURL *)url {

    [self sd_cancelCurrentImageLoad];

    self.alpha = 0.0;

    [self sd_setImageWithURL:url placeholderImage:nil options:SDWebImageRetryFailed completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

        if (image) {

            BOOL animated = NO;

            if (cacheType == SDImageCacheTypeDisk || cacheType == SDImageCacheTypeNone) {
                animated = YES;
            }

            self.image = image;

            if (animated) {

                [UIView animateWithDuration:ANIMATION_DURATION animations:^{

                    self.alpha = 1.0;

                }];

            } else {

                self.alpha = 1.0;

            }
        }

    }];

}
Run Code Online (Sandbox Code Playgroud)

小智 5

我偶然发现了这一点,并且已经在各种项目上做到这一点.这里的关键是阻止图像自动设置的选项.然后我们检查缓存类型并做一个很棒的交叉淡入淡出.您还可以在加载内容时设置占位符图像,或者如果在加载某些内容时需要纯色背景,则可以设置图像视图的背景颜色.

[self.mediaImage sd_setImageWithURL:[NSURL URLWithString:content.previewUrl]
                       placeholderImage:nil
                                options:SDWebImageAvoidAutoSetImage
                              completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                                  if ([imageURL isEqual:[NSURL URLWithString:content.previewUrl]]) {
                                      if (cacheType == SDImageCacheTypeMemory) {
                                          self.mediaImage.image = image;
                                      } else {
                                          [UIView transitionWithView:self.mediaImage
                                                            duration:.3
                                                             options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                                                                 self.mediaImage.image = image;
                                                             }
                                                          completion:nil];
                                      }
                                  }
                              }];
Run Code Online (Sandbox Code Playgroud)