YYWebImageManager.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // YYWebImageManager.m
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 15/2/19.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import "YYWebImageManager.h"
  12. #import "YYImageCache.h"
  13. #import "YYWebImageOperation.h"
  14. #import <objc/runtime.h>
  15. #define kNetworkIndicatorDelay (1/30.0)
  16. @interface _YYUIApplicationNetworkIndicatorInfo : NSObject
  17. @property (nonatomic, assign) NSInteger count;
  18. @property (nonatomic, strong) NSTimer *timer;
  19. @end
  20. @implementation _YYUIApplicationNetworkIndicatorInfo
  21. @end
  22. @implementation YYWebImageManager
  23. + (instancetype)sharedManager {
  24. static YYWebImageManager *manager;
  25. static dispatch_once_t onceToken;
  26. dispatch_once(&onceToken, ^{
  27. YYImageCache *cache = [YYImageCache sharedCache];
  28. NSOperationQueue *queue = [NSOperationQueue new];
  29. if ([queue respondsToSelector:@selector(setQualityOfService:)]) {
  30. queue.qualityOfService = NSQualityOfServiceBackground;
  31. }
  32. manager = [[self alloc] initWithCache:cache queue:queue];
  33. });
  34. return manager;
  35. }
  36. - (instancetype)init {
  37. @throw [NSException exceptionWithName:@"YYWebImageManager init error" reason:@"Use the designated initializer to init." userInfo:nil];
  38. return [self initWithCache:nil queue:nil];
  39. }
  40. - (instancetype)initWithCache:(YYImageCache *)cache queue:(NSOperationQueue *)queue{
  41. self = [super init];
  42. if (!self) return nil;
  43. _cache = cache;
  44. _queue = queue;
  45. _timeout = 15.0;
  46. _headers = @{ @"Accept" : @"image/webp,image/*;q=0.8" };
  47. return self;
  48. }
  49. - (YYWebImageOperation *)requestImageWithURL:(NSURL *)url
  50. options:(YYWebImageOptions)options
  51. progress:(YYWebImageProgressBlock)progress
  52. transform:(YYWebImageTransformBlock)transform
  53. completion:(YYWebImageCompletionBlock)completion {
  54. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  55. request.timeoutInterval = _timeout;
  56. request.HTTPShouldHandleCookies = (options & YYWebImageOptionHandleCookies) != 0;
  57. request.allHTTPHeaderFields = [self headersForURL:url];
  58. request.HTTPShouldUsePipelining = YES;
  59. request.cachePolicy = (options & YYWebImageOptionUseNSURLCache) ?
  60. NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
  61. YYWebImageOperation *operation = [[YYWebImageOperation alloc] initWithRequest:request
  62. options:options
  63. cache:_cache
  64. cacheKey:[self cacheKeyForURL:url]
  65. progress:progress
  66. transform:transform ? transform : _sharedTransformBlock
  67. completion:completion];
  68. if (_username && _password) {
  69. operation.credential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceForSession];
  70. }
  71. if (operation) {
  72. NSOperationQueue *queue = _queue;
  73. if (queue) {
  74. [queue addOperation:operation];
  75. } else {
  76. [operation start];
  77. }
  78. }
  79. return operation;
  80. }
  81. - (NSDictionary *)headersForURL:(NSURL *)url {
  82. if (!url) return nil;
  83. return _headersFilter ? _headersFilter(url, _headers) : _headers;
  84. }
  85. - (NSString *)cacheKeyForURL:(NSURL *)url {
  86. if (!url) return nil;
  87. return _cacheKeyFilter ? _cacheKeyFilter(url) : url.absoluteString;
  88. }
  89. #pragma mark Network Indicator
  90. + (_YYUIApplicationNetworkIndicatorInfo *)_networkIndicatorInfo {
  91. return objc_getAssociatedObject(self, @selector(_networkIndicatorInfo));
  92. }
  93. + (void)_setNetworkIndicatorInfo:(_YYUIApplicationNetworkIndicatorInfo *)info {
  94. objc_setAssociatedObject(self, @selector(_networkIndicatorInfo), info, OBJC_ASSOCIATION_RETAIN);
  95. }
  96. + (void)_delaySetActivity:(NSTimer *)timer {
  97. NSNumber *visiable = timer.userInfo;
  98. if ([UIApplication sharedApplication].networkActivityIndicatorVisible != visiable.boolValue) {
  99. [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:visiable.boolValue];
  100. }
  101. [timer invalidate];
  102. }
  103. + (void)_changeNetworkActivityCount:(NSInteger)delta {
  104. void (^block)() = ^{
  105. _YYUIApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo];
  106. if (!info) {
  107. info = [_YYUIApplicationNetworkIndicatorInfo new];
  108. [self _setNetworkIndicatorInfo:info];
  109. }
  110. NSInteger count = info.count;
  111. count += delta;
  112. info.count = count;
  113. [info.timer invalidate];
  114. info.timer = [NSTimer timerWithTimeInterval:kNetworkIndicatorDelay target:self selector:@selector(_delaySetActivity:) userInfo:@(info.count > 0) repeats:NO];
  115. [[NSRunLoop mainRunLoop] addTimer:info.timer forMode:NSRunLoopCommonModes];
  116. };
  117. if ([NSThread isMainThread]) {
  118. block();
  119. } else {
  120. dispatch_async(dispatch_get_main_queue(), block);
  121. }
  122. }
  123. + (void)incrementNetworkActivityCount {
  124. [self _changeNetworkActivityCount:1];
  125. }
  126. + (void)decrementNetworkActivityCount {
  127. [self _changeNetworkActivityCount:-1];
  128. }
  129. + (NSInteger)currentNetworkActivityCount {
  130. _YYUIApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo];
  131. return info.count;
  132. }
  133. @end