簡體   English   中英

iOS解決方案只有在尚未使用SDWebImage在內存中緩存時才能使用動畫加載圖像

[英]iOS solution to load images with animation only if they are not already cached in memory with SDWebImage

我幾天來一直在努力解決這個問題。 以前我使用AFNetworking類來加載和緩存圖像,但它沒有在它的回調中提供緩存類型。 所以我曾經在每個控制器中跟蹤哪些圖像已經加載。 我瀏覽了SDWebImage,它提供了我正在尋找的東西 - SDImageCacheType

現在我試圖想出一個易於使用(希望是一個單行)的解決方案來加載表格和集合視圖中的圖像,如果它們被下載或來自磁盤緩存。 基本上這些任務需要一些時間才能獲得實際圖像,當內存緩存瞬間提供圖像時,因此當圖像來自內存時不需要動畫。

我想出了這個UIImageView類別,我希望有更有經驗的人提供一些反饋。 它確實似乎按預期工作。 我不確定我是在這里重新發明輪子,否則這種做法在某些情況下可能會適得其反。

概述是做兩件事。 在完成塊中,當圖像准備好使用時,它根據已使用的緩存級別設置動畫持續時間。 第二個想法是可重復使用的單元機制,imageView在相關對象的幫助下跟蹤加載操作,如果有正在進行的任務則取消它。 AFNetworking解決方案不需要這樣做,因為當您設置新的解決方案時,它會默認取消正在進行的圖像加載。 我不喜歡這樣的事實,即操作被保留,它不應該是,但是關聯的對象不提供__weak類型的引用afaik。 OBJC_ASSOCIATION_ASSIGN鍵似乎使對象__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;

    }

--- 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;

            }
        }

    }];

}

我偶然發現了這一點,並且已經在各種項目中做到了這一點。 這里的關鍵是阻止圖像自動設置的選項。 然后我們檢查緩存類型並做一個很棒的交叉淡入淡出。 您還可以在加載內容時設置占位符圖像,或者如果在加載某些內容時需要純色背景,則可以設置圖像視圖的背景顏色。

[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];
                                      }
                                  }
                              }];

您使用SDWebImageManager手動下載圖像的任何特殊原因? SDWebImage已經提供了一個UIImageView類,其中包含可以直接在UIImageView上調用的方法。

這是我將如何解決問題:

#import <UIImageView+WebCache.h>

// let's say we wanted to do a fade-in animation
imageView.alpha = 0.f;

[imageView sd_setImageWithURL:url completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
    if (cacheType == SDImageCacheTypeNone) {
        [UIView animateWithDuration:0.3 animations:^{
            imageView.alpha = 1.f;
        }];
    } else {
        imageView.alpha = 1.f;
    }
}];

此外,作為旁注,執行持續時間為0.0的動畫可能在邏輯上是瞬時的,但iOS仍然會引入整個動畫操作的開銷,這不僅會降低性能,還會增加一點延遲,否則會沒有動畫就看不到。

使用這里列出的答案,我能夠為swift整理一個版本。

imageView.sd_setImage(with: imageURL, placeholderImage: imageView.image, options: .avoidAutoSetImage, completed: { (image, error, cache, url) in
    UIView.transition(with: self, duration: 1.35, options: .transitionCrossDissolve, animations: {
        self.imageView.image = image
    }, completion: nil)
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM