Authored by Bogdan Poplauschi

Built a FLAnimatedImageView category that hooks this class to the SDWebImage sys…

…tem. It's very similar to UIImageView (WebCache). There are explicit methods for loading an animated image.
  1 +/*
  2 + * This file is part of the SDWebImage package.
  3 + * (c) Olivier Poitrey <rs@dailymotion.com>
  4 + *
  5 + * For the full copyright and license information, please view the LICENSE
  6 + * file that was distributed with this source code.
  7 + */
  8 +
  9 +
  10 +#if COCOAPODS
  11 + @import FLAnimatedImage;
  12 +#else
  13 + #import "FLAnimatedImageView.h"
  14 +#endif
  15 +
  16 +#import "SDWebImageManager.h"
  17 +
  18 +
  19 +/**
  20 + * A category for the FLAnimatedImage imageView class that hooks it to the SDWebImage system.
  21 + * Very similar to the base class category (UIImageView (WebCache))
  22 + */
  23 +@interface FLAnimatedImageView (WebCache)
  24 +
  25 +/**
  26 + * Get the current image URL.
  27 + *
  28 + * Note that because of the limitations of categories this property can get out of sync
  29 + * if you use setImage: directly.
  30 + */
  31 +- (NSURL *)sd_imageURL;
  32 +
  33 +/**
  34 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  35 + * The download is asynchronous and cached.
  36 + *
  37 + * @param url The url for the image.
  38 + */
  39 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url;
  40 +
  41 +/**
  42 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  43 + * The download is asynchronous and cached.
  44 + * Uses a placeholder until the request finishes.
  45 + *
  46 + * @param url The url for the image.
  47 + * @param placeholder The image to be set initially, until the image request finishes.
  48 + */
  49 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
  50 +
  51 +/**
  52 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  53 + * The download is asynchronous and cached.
  54 + * Uses a placeholder until the request finishes.
  55 + *
  56 + * @param url The url for the image.
  57 + * @param placeholder The image to be set initially, until the image request finishes.
  58 + * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
  59 + */
  60 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
  61 +
  62 +/**
  63 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  64 + * The download is asynchronous and cached.
  65 + *
  66 + * @param url The url for the image.
  67 + * @param completedBlock A block called when operation has been completed. This block has no return value
  68 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  69 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  70 + * indicating if the image was retrieved from the local cache or from the network.
  71 + * The fourth parameter is the original image url.
  72 + */
  73 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url completed:(SDExternalCompletionBlock)completedBlock;
  74 +
  75 +/**
  76 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  77 + * The download is asynchronous and cached.
  78 + * Uses a placeholder until the request finishes.
  79 + *
  80 + * @param url The url for the image.
  81 + * @param placeholder The image to be set initially, until the image request finishes.
  82 + * @param completedBlock A block called when operation has been completed. This block has no return value
  83 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  84 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  85 + * indicating if the image was retrieved from the local cache or from the network.
  86 + * The fourth parameter is the original image url.
  87 + */
  88 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDExternalCompletionBlock)completedBlock;
  89 +
  90 +/**
  91 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  92 + * The download is asynchronous and cached.
  93 + * Uses a placeholder until the request finishes.
  94 + *
  95 + * @param url The url for the image.
  96 + * @param placeholder The image to be set initially, until the image request finishes.
  97 + * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
  98 + * @param completedBlock A block called when operation has been completed. This block has no return value
  99 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  100 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  101 + * indicating if the image was retrieved from the local cache or from the network.
  102 + * The fourth parameter is the original image url.
  103 + */
  104 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDExternalCompletionBlock)completedBlock;
  105 +
  106 +/**
  107 + * Load the image at the given url (either from cache or download) and load it in this imageView. It works with both static and dynamic images
  108 + * The download is asynchronous and cached.
  109 + * Uses a placeholder until the request finishes.
  110 + *
  111 + * @param url The url for the image.
  112 + * @param placeholder The image to be set initially, until the image request finishes.
  113 + * @param options The options to use when downloading the image. @see SDWebImageOptions for the possible values.
  114 + * @param progressBlock A block called while image is downloading
  115 + * @param completedBlock A block called when operation has been completed. This block has no return value
  116 + * and takes the requested UIImage as first parameter. In case of error the image parameter
  117 + * is nil and the second parameter may contain an NSError. The third parameter is a Boolean
  118 + * indicating if the image was retrieved from the local cache or from the network.
  119 + * The fourth parameter is the original image url.
  120 + */
  121 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDExternalCompletionBlock)completedBlock;
  122 +
  123 +/**
  124 + * Cancel the image load
  125 + */
  126 +- (void)sd_cancelCurrentAnimatedImageLoad;
  127 +
  128 +@end
  1 +/*
  2 + * This file is part of the SDWebImage package.
  3 + * (c) Olivier Poitrey <rs@dailymotion.com>
  4 + *
  5 + * For the full copyright and license information, please view the LICENSE
  6 + * file that was distributed with this source code.
  7 + */
  8 +
  9 +
  10 +#import "FLAnimatedImageView+WebCache.h"
  11 +#import "objc/runtime.h"
  12 +#import "UIView+WebCacheOperation.h"
  13 +#import "NSData+ImageContentType.h"
  14 +#import "FLAnimatedImage.h"
  15 +#import "UIImageView+WebCache.h"
  16 +
  17 +static char imageURLKey;
  18 +
  19 +
  20 +@implementation FLAnimatedImageView (WebCache)
  21 +
  22 +- (NSURL *)sd_imageURL {
  23 + return objc_getAssociatedObject(self, &imageURLKey);
  24 +}
  25 +
  26 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url {
  27 + [self sd_setAnimatedImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
  28 +}
  29 +
  30 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder {
  31 + [self sd_setAnimatedImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
  32 +}
  33 +
  34 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options {
  35 + [self sd_setAnimatedImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
  36 +}
  37 +
  38 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url completed:(SDExternalCompletionBlock)completedBlock {
  39 + [self sd_setAnimatedImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
  40 +}
  41 +
  42 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDExternalCompletionBlock)completedBlock {
  43 + [self sd_setAnimatedImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
  44 +}
  45 +
  46 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDExternalCompletionBlock)completedBlock {
  47 + [self sd_setAnimatedImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
  48 +}
  49 +
  50 +- (void)sd_setAnimatedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDExternalCompletionBlock)completedBlock {
  51 + [self sd_cancelCurrentAnimatedImageLoad];
  52 + objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  53 +
  54 + if (!(options & SDWebImageDelayPlaceholder)) {
  55 + dispatch_main_async_safe(^{
  56 + self.image = placeholder;
  57 + });
  58 + }
  59 +
  60 + if (url) {
  61 + // check if activityView is enabled or not
  62 + if ([self showActivityIndicatorView]) {
  63 + [self addActivityIndicator];
  64 + }
  65 +
  66 + __weak __typeof(self)wself = self;
  67 + id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
  68 + if (!wself) return;
  69 + dispatch_main_sync_safe(^{
  70 + [wself removeActivityIndicator];
  71 +
  72 + if (!wself) return;
  73 + if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) {
  74 + completedBlock(image, error, cacheType, url);
  75 + return;
  76 + } else if (image) {
  77 + NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
  78 + if ([imageContentType isEqualToString:@"image/gif"]) {
  79 + wself.animatedImage = [FLAnimatedImage animatedImageWithGIFData:data];
  80 + wself.image = nil;
  81 + } else {
  82 + wself.image = image;
  83 + wself.animatedImage = nil;
  84 + }
  85 + [wself setNeedsLayout];
  86 + } else {
  87 + if ((options & SDWebImageDelayPlaceholder)) {
  88 + wself.image = placeholder;
  89 + [wself setNeedsLayout];
  90 + }
  91 + }
  92 + if (completedBlock && finished) {
  93 + completedBlock(image, error, cacheType, url);
  94 + }
  95 + });
  96 + }];
  97 + [self sd_setImageLoadOperation:operation forKey:@"UIImageViewAnimatedImageLoad"];
  98 + } else {
  99 + dispatch_main_async_safe(^{
  100 + [self removeActivityIndicator];
  101 +
  102 + if (completedBlock) {
  103 + NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
  104 + completedBlock(nil, error, SDImageCacheTypeNone, url);
  105 + }
  106 + });
  107 + }
  108 +}
  109 +
  110 +- (void)sd_cancelCurrentAnimatedImageLoad {
  111 + [self sd_cancelImageLoadOperationWithKey:@"UIImageViewAnimatedImageLoad"];
  112 +}
  113 +
  114 +
  115 +@end