UIImageView+WebCache.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. #import "UIImageView+WebCache.h"
  9. #import "objc/runtime.h"
  10. #import "UIView+WebCacheOperation.h"
  11. #import "UIView+WebCache.h"
  12. @implementation UIImageView (WebCache)
  13. - (void)sd_setImageWithURL:(nullable NSURL *)url {
  14. [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
  15. }
  16. - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder {
  17. [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil];
  18. }
  19. - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options {
  20. [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil];
  21. }
  22. - (void)sd_setImageWithURL:(nullable NSURL *)url completed:(nullable SDExternalCompletionBlock)completedBlock {
  23. [self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock];
  24. }
  25. - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock {
  26. [self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock];
  27. }
  28. - (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options completed:(nullable SDExternalCompletionBlock)completedBlock {
  29. [self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock];
  30. }
  31. - (void)sd_setImageWithURL:(nullable NSURL *)url
  32. placeholderImage:(nullable UIImage *)placeholder
  33. options:(SDWebImageOptions)options
  34. progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
  35. completed:(nullable SDExternalCompletionBlock)completedBlock {
  36. [self sd_internalSetImageWithURL:url
  37. placeholderImage:placeholder
  38. options:options
  39. operationKey:nil
  40. setImageBlock:nil
  41. progress:progressBlock
  42. completed:completedBlock];
  43. }
  44. - (void)sd_setImageWithPreviousCachedImageWithURL:(nullable NSURL *)url
  45. placeholderImage:(nullable UIImage *)placeholder
  46. options:(SDWebImageOptions)options
  47. progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
  48. completed:(nullable SDExternalCompletionBlock)completedBlock {
  49. NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
  50. UIImage *lastPreviousCachedImage = [[SDImageCache sharedImageCache] imageFromCacheForKey:key];
  51. [self sd_setImageWithURL:url placeholderImage:lastPreviousCachedImage ?: placeholder options:options progress:progressBlock completed:completedBlock];
  52. }
  53. #if SD_UIKIT
  54. #pragma mark - Animation of multiple images
  55. - (void)sd_setAnimationImagesWithURLs:(nonnull NSArray<NSURL *> *)arrayOfURLs {
  56. [self sd_cancelCurrentAnimationImagesLoad];
  57. NSPointerArray *operationsArray = [self sd_animationOperationArray];
  58. [arrayOfURLs enumerateObjectsUsingBlock:^(NSURL *logoImageURL, NSUInteger idx, BOOL * _Nonnull stop) {
  59. __weak __typeof(self) wself = self;
  60. id <SDWebImageOperation> operation = [[SDWebImageManager sharedManager] loadImageWithURL:logoImageURL options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
  61. __strong typeof(wself) sself = wself;
  62. if (!sself) return;
  63. dispatch_main_async_safe(^{
  64. [sself stopAnimating];
  65. if (sself && image) {
  66. NSMutableArray<UIImage *> *currentImages = [[sself animationImages] mutableCopy];
  67. if (!currentImages) {
  68. currentImages = [[NSMutableArray alloc] init];
  69. }
  70. // We know what index objects should be at when they are returned so
  71. // we will put the object at the index, filling any empty indexes
  72. // with the image that was returned too "early". These images will
  73. // be overwritten. (does not require additional sorting datastructure)
  74. while ([currentImages count] < idx) {
  75. [currentImages addObject:image];
  76. }
  77. currentImages[idx] = image;
  78. sself.animationImages = currentImages;
  79. [sself setNeedsLayout];
  80. }
  81. [sself startAnimating];
  82. });
  83. }];
  84. @synchronized (self) {
  85. [operationsArray addPointer:(__bridge void *)(operation)];
  86. }
  87. }];
  88. }
  89. static char animationLoadOperationKey;
  90. // element is weak because operation instance is retained by SDWebImageManager's runningOperations property
  91. // we should use lock to keep thread-safe because these method may not be acessed from main queue
  92. - (NSPointerArray *)sd_animationOperationArray {
  93. @synchronized(self) {
  94. NSPointerArray *operationsArray = objc_getAssociatedObject(self, &animationLoadOperationKey);
  95. if (operationsArray) {
  96. return operationsArray;
  97. }
  98. operationsArray = [NSPointerArray weakObjectsPointerArray];
  99. objc_setAssociatedObject(self, &animationLoadOperationKey, operationsArray, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  100. return operationsArray;
  101. }
  102. }
  103. - (void)sd_cancelCurrentAnimationImagesLoad {
  104. NSPointerArray *operationsArray = [self sd_animationOperationArray];
  105. if (operationsArray) {
  106. @synchronized (self) {
  107. for (id operation in operationsArray) {
  108. if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
  109. [operation cancel];
  110. }
  111. }
  112. operationsArray.count = 0;
  113. }
  114. }
  115. }
  116. #endif
  117. @end