UIImageView+AFNetworking.m 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // UIImageView+AFNetworking.m
  2. // Copyright (c) 2011–2016 Alamofire Software Foundation ( http://alamofire.org/ )
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. #import "UIImageView+AFNetworking.h"
  22. #import <objc/runtime.h>
  23. #if TARGET_OS_IOS || TARGET_OS_TV
  24. #import "AFImageDownloader.h"
  25. @interface UIImageView (_AFNetworking)
  26. @property (readwrite, nonatomic, strong, setter = af_setActiveImageDownloadReceipt:) AFImageDownloadReceipt *af_activeImageDownloadReceipt;
  27. @end
  28. @implementation UIImageView (_AFNetworking)
  29. - (AFImageDownloadReceipt *)af_activeImageDownloadReceipt {
  30. return (AFImageDownloadReceipt *)objc_getAssociatedObject(self, @selector(af_activeImageDownloadReceipt));
  31. }
  32. - (void)af_setActiveImageDownloadReceipt:(AFImageDownloadReceipt *)imageDownloadReceipt {
  33. objc_setAssociatedObject(self, @selector(af_activeImageDownloadReceipt), imageDownloadReceipt, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  34. }
  35. @end
  36. #pragma mark -
  37. @implementation UIImageView (AFNetworking)
  38. + (AFImageDownloader *)sharedImageDownloader {
  39. return objc_getAssociatedObject(self, @selector(sharedImageDownloader)) ?: [AFImageDownloader defaultInstance];
  40. }
  41. + (void)setSharedImageDownloader:(AFImageDownloader *)imageDownloader {
  42. objc_setAssociatedObject(self, @selector(sharedImageDownloader), imageDownloader, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  43. }
  44. #pragma mark -
  45. - (void)setImageWithURL:(NSURL *)url {
  46. [self setImageWithURL:url placeholderImage:nil];
  47. }
  48. - (void)setImageWithURL:(NSURL *)url
  49. placeholderImage:(UIImage *)placeholderImage
  50. {
  51. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  52. [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
  53. [self setImageWithURLRequest:request placeholderImage:placeholderImage success:nil failure:nil];
  54. }
  55. - (void)setImageWithURLRequest:(NSURLRequest *)urlRequest
  56. placeholderImage:(UIImage *)placeholderImage
  57. success:(void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, UIImage *image))success
  58. failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure
  59. {
  60. if ([urlRequest URL] == nil) {
  61. self.image = placeholderImage;
  62. if (failure) {
  63. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorBadURL userInfo:nil];
  64. failure(urlRequest, nil, error);
  65. }
  66. return;
  67. }
  68. if ([self isActiveTaskURLEqualToURLRequest:urlRequest]){
  69. return;
  70. }
  71. [self cancelImageDownloadTask];
  72. AFImageDownloader *downloader = [[self class] sharedImageDownloader];
  73. id <AFImageRequestCache> imageCache = downloader.imageCache;
  74. //Use the image from the image cache if it exists
  75. UIImage *cachedImage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil];
  76. if (cachedImage) {
  77. if (success) {
  78. success(urlRequest, nil, cachedImage);
  79. } else {
  80. self.image = cachedImage;
  81. }
  82. [self clearActiveDownloadInformation];
  83. } else {
  84. if (placeholderImage) {
  85. self.image = placeholderImage;
  86. }
  87. __weak __typeof(self)weakSelf = self;
  88. NSUUID *downloadID = [NSUUID UUID];
  89. AFImageDownloadReceipt *receipt;
  90. receipt = [downloader
  91. downloadImageForURLRequest:urlRequest
  92. withReceiptID:downloadID
  93. success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull responseObject) {
  94. __strong __typeof(weakSelf)strongSelf = weakSelf;
  95. if ([strongSelf.af_activeImageDownloadReceipt.receiptID isEqual:downloadID]) {
  96. if (success) {
  97. success(request, response, responseObject);
  98. } else if(responseObject) {
  99. strongSelf.image = responseObject;
  100. }
  101. [strongSelf clearActiveDownloadInformation];
  102. }
  103. }
  104. failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {
  105. __strong __typeof(weakSelf)strongSelf = weakSelf;
  106. if ([strongSelf.af_activeImageDownloadReceipt.receiptID isEqual:downloadID]) {
  107. if (failure) {
  108. failure(request, response, error);
  109. }
  110. [strongSelf clearActiveDownloadInformation];
  111. }
  112. }];
  113. self.af_activeImageDownloadReceipt = receipt;
  114. }
  115. }
  116. - (void)cancelImageDownloadTask {
  117. if (self.af_activeImageDownloadReceipt != nil) {
  118. [[self.class sharedImageDownloader] cancelTaskForImageDownloadReceipt:self.af_activeImageDownloadReceipt];
  119. [self clearActiveDownloadInformation];
  120. }
  121. }
  122. - (void)clearActiveDownloadInformation {
  123. self.af_activeImageDownloadReceipt = nil;
  124. }
  125. - (BOOL)isActiveTaskURLEqualToURLRequest:(NSURLRequest *)urlRequest {
  126. return [self.af_activeImageDownloadReceipt.task.originalRequest.URL.absoluteString isEqualToString:urlRequest.URL.absoluteString];
  127. }
  128. @end
  129. #endif