Bez popisu

UIImageView+XHURLDownload.m 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. // UIImageView+XHURLDownload.m
  3. // XHImageViewer
  4. //
  5. // Created by 曾 宪华 on 14-2-18.
  6. // Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
  7. //
  8. #import "UIImageView+XHURLDownload.h"
  9. #import <objc/runtime.h>
  10. const char* const kXHURLPropertyKey = "XHURLDownloadURLPropertyKey";
  11. const char* const kCLLoadingStateKey = "XHURLDownloadLoadingStateKey";
  12. const char* const kCLLoadingViewKey = "XHURLDownloadLoadingViewKey";
  13. @implementation UIImageView (XHURLDownload)
  14. + (id)imageViewWithURL:(NSURL*)url autoLoading:(BOOL)autoLoading {
  15. UIImageView *view = [self new];
  16. view.url = url;
  17. if(autoLoading) {
  18. [view load];
  19. }
  20. return view;
  21. }
  22. + (id)indicatorImageView {
  23. UIImageView *view = [self new];
  24. [view setDefaultLoadingView];
  25. return view;
  26. }
  27. + (id)indicatorImageViewWithURL:(NSURL*)url autoLoading:(BOOL)autoLoading {
  28. UIImageView *view = [self imageViewWithURL:url autoLoading:autoLoading];
  29. [view setDefaultLoadingView];
  30. return view;
  31. }
  32. #pragma mark- Properties
  33. - (NSURL*)url {
  34. return objc_getAssociatedObject(self, kXHURLPropertyKey);
  35. }
  36. - (void)setUrl:(NSURL *)url {
  37. [self setUrl:url autoLoading:NO];
  38. }
  39. - (void)setUrl:(NSURL *)url autoLoading:(BOOL)autoLoading {
  40. if(![url isEqual:self.url]) {
  41. objc_setAssociatedObject(self, kXHURLPropertyKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  42. if (url) {
  43. self.loadingState = UIImageViewURLDownloadStateWaitingForLoad;
  44. }
  45. else {
  46. self.loadingState = UIImageViewURLDownloadStateUnknown;
  47. }
  48. }
  49. if(autoLoading) {
  50. [self load];
  51. }
  52. }
  53. - (void)loadWithURL:(NSURL *)url {
  54. [self setUrl:url autoLoading:YES];
  55. }
  56. - (void)loadWithURL:(NSURL*)url completionBlock:(void(^)(UIImage *image, NSURL *url, NSError *error))handler {
  57. [self setUrl:url autoLoading:NO];
  58. [self loadWithCompletionBlock:handler];
  59. }
  60. - (UIImageViewURLDownloadState)loadingState {
  61. return (NSUInteger)([objc_getAssociatedObject(self, kCLLoadingStateKey) integerValue]);
  62. }
  63. - (void)setLoadingState:(UIImageViewURLDownloadState)loadingState {
  64. objc_setAssociatedObject(self, kCLLoadingStateKey, @(loadingState), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  65. }
  66. - (UIView *)loadingView {
  67. return objc_getAssociatedObject(self, kCLLoadingViewKey);
  68. }
  69. - (void)setLoadingView:(UIView *)loadingView {
  70. [self.loadingView removeFromSuperview];
  71. objc_setAssociatedObject(self, kCLLoadingViewKey, loadingView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  72. loadingView.center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
  73. loadingView.alpha = 0;
  74. [self addSubview:loadingView];
  75. }
  76. - (void)setDefaultLoadingView {
  77. UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
  78. indicator.frame = self.frame;
  79. indicator.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  80. indicator.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1];
  81. self.loadingView = indicator;
  82. }
  83. #pragma mark- Loading view
  84. - (void)showLoadingView {
  85. dispatch_async(dispatch_get_main_queue(), ^{
  86. self.loadingView.alpha = 1;
  87. if([self.loadingView respondsToSelector:@selector(startAnimating)]) {
  88. [self.loadingView performSelector:@selector(startAnimating)];
  89. }
  90. });
  91. }
  92. - (void)hideLoadingView {
  93. dispatch_async(dispatch_get_main_queue(), ^{
  94. [UIView animateWithDuration:0.3
  95. animations:^{
  96. self.loadingView.alpha = 0;
  97. }
  98. completion:^(BOOL finished) {
  99. if([self.loadingView respondsToSelector:@selector(stopAnimating)]) {
  100. [self.loadingView performSelector:@selector(stopAnimating)];
  101. }
  102. }
  103. ];
  104. });
  105. }
  106. #pragma mark- Image downloading
  107. + (NSOperationQueue *)downloadQueue {
  108. static NSOperationQueue *_sharedQueue = nil;
  109. if(_sharedQueue==nil) {
  110. _sharedQueue = [NSOperationQueue new];
  111. [_sharedQueue setMaxConcurrentOperationCount:3];
  112. }
  113. return _sharedQueue;
  114. }
  115. + (void)dataWithContentsOfURL:(NSURL *)url completionBlock:(void (^)(NSURL *, NSData *, NSError *))completion {
  116. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  117. [request setHTTPMethod:@"GET"];
  118. [request setTimeoutInterval:5.0];
  119. [NSURLConnection sendAsynchronousRequest:request
  120. queue:[self downloadQueue]
  121. completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
  122. if(completion){
  123. completion(url, data, connectionError);
  124. }
  125. }
  126. ];
  127. }
  128. - (void)load {
  129. [self loadWithCompletionBlock:nil];
  130. }
  131. - (void)loadWithCompletionBlock:(void(^)(UIImage *image, NSURL *url, NSError *error))handler {
  132. self.loadingState = UIImageViewURLDownloadStateNowLoading;
  133. [self showLoadingView];
  134. // It could be more better by replacing with a method that has delegates like a progress.
  135. [UIImageView dataWithContentsOfURL:self.url
  136. completionBlock:^(NSURL *url, NSData *data, NSError *error) {
  137. UIImage *image = [self didFinishDownloadWithData:data forURL:url error:error];
  138. if(handler) {
  139. handler(image, url, error);
  140. }
  141. }
  142. ];
  143. }
  144. - (UIImage *)didFinishDownloadWithData:(NSData *)data forURL:(NSURL *)url error:(NSError *)error {
  145. UIImage *image = [UIImage imageWithData:data];
  146. if([url isEqual:self.url]) {
  147. if(error) {
  148. self.loadingState = UIImageViewURLDownloadStateFailed;
  149. }
  150. else {
  151. [self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
  152. self.loadingState = UIImageViewURLDownloadStateLoaded;
  153. }
  154. [self hideLoadingView];
  155. }
  156. return image;
  157. }
  158. - (void)setImage:(UIImage *)image forURL:(NSURL *)url {
  159. if([url isEqual:self.url]) {
  160. [self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
  161. self.loadingState = UIImageViewURLDownloadStateLoaded;
  162. [self hideLoadingView];
  163. }
  164. }
  165. @end