123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- /*
- * This file is part of the SDWebImage package.
- * (c) Olivier Poitrey <rs@dailymotion.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- #import "UIImageView+WebCache.h"
- #import "objc/runtime.h"
- #import "UIView+WebCacheOperation.h"
- #import "UIView+WebCache.h"
- @implementation UIImageView (WebCache)
- - (void)sd_setImageWithURL:(nullable NSURL *)url {
- [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
- }
- - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
- [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
- }
- - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
- [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
- }
- - (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
- [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
- }
- - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
- [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
- }
- - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
- [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
- }
- - (void)sd_setImageWithURL:(nullable NSURL *)url
- placeholderImage:(nullable UIImage *)placeholder
- options:(SDWebImageOptions)options
- progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
- completed:(nullable SDExternalCompletionBlock)completedBlock {
- [self sd_internalSetImageWithURL:url
- placeholderImage:placeholder
- options:options
- operationKey:nil
- setImageBlock:nil
- progress:progressBlock
- completed:completedBlock];
- }
- - (void)sd_setImageWithPreviousCachedImageWithURL:(nullable NSURL *)url
- placeholderImage:(nullable UIImage *)placeholder
- options:(SDWebImageOptions)options
- progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
- completed:(nullable SDExternalCompletionBlock)completedBlock {
- NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
- UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromCacheForKey:key];
-
- [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock];
- }
- #if SD_UIKIT
- #pragma mark - Animation of multiple images
- - (void)sd_setAnimationImagesWithURLs:(nonnull NSArray<NSURL *> *)arrayOfURLs {
- [self sd_cancelCurrentAnimationImagesLoad];
- NSPointerArray *operationsArray = [self sd_animationOperationArray];
-
- [arrayOfURLs enumerateObjectsUsingBlock:^(NSURL *logoImageURL, NSUInteger idx, BOOL * _Nonnull stop) {
- __weak __typeof(self) wself = self;
- id <SDWebImageOperation> operation = [[SDWebImageManager sharedManager] loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
- __strong typeof(wself) sself = wself;
- if (!sself) return;
- dispatch_main_async_safe(^{
- [sself stopAnimating];
- if (sself && image) {
- NSMutableArray<UIImage *> *currentImages = [[sself animationImages] mutableCopy];
- if (!currentImages) {
- currentImages = [[NSMutableArray alloc] init];
- }
-
- // We know what index objects should be at when they are returned so
- // we will put the object at the index, filling any empty indexes
- // with the image that was returned too "early". These images will
- // be overwritten. (does not require additional sorting datastructure)
- while ([currentImages count] < idx) {
- [currentImages addObject:image];
- }
-
- currentImages[idx] = image;
- sself.animationImages = currentImages;
- [sself setNeedsLayout];
- }
- [sself startAnimating];
- });
- }];
- @synchronized (self) {
- [operationsArray addPointer:(__bridge void *)(operation)];
- }
- }];
- }
- static char animationLoadOperationKey;
- // element is weak because operation instance is retained by SDWebImageManager's runningOperations property
- // we should use lock to keep thread-safe because these method may not be acessed from main queue
- - (NSPointerArray *)sd_animationOperationArray {
- @synchronized(self) {
- NSPointerArray *operationsArray = objc_getAssociatedObject(self, &animationLoadOperationKey);
- if (operationsArray) {
- return operationsArray;
- }
- operationsArray = [NSPointerArray weakObjectsPointerArray];
- objc_setAssociatedObject(self, &animationLoadOperationKey, operationsArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
- return operationsArray;
- }
- }
- - (void)sd_cancelCurrentAnimationImagesLoad {
- NSPointerArray *operationsArray = [self sd_animationOperationArray];
- if (operationsArray) {
- @synchronized (self) {
- for (id operation in operationsArray) {
- if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
- [operation cancel];
- }
- }
- operationsArray.count = 0;
- }
- }
- }
- #endif
- @end
|