123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- //
- // YYWebImageManager.m
- // YYWebImage <https://github.com/ibireme/YYWebImage>
- //
- // Created by ibireme on 15/2/19.
- // Copyright (c) 2015 ibireme.
- //
- // This source code is licensed under the MIT-style license found in the
- // LICENSE file in the root directory of this source tree.
- //
- #import "YYWebImageManager.h"
- #import "YYImageCache.h"
- #import "YYWebImageOperation.h"
- #import "YYImageCoder.h"
- #import <objc/runtime.h>
- #define kNetworkIndicatorDelay (1/30.0)
- /// Returns nil in App Extension.
- static UIApplication *_YYSharedApplication() {
- static BOOL isAppExtension = NO;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- Class cls = NSClassFromString(@"UIApplication");
- if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES;
- if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES;
- });
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wundeclared-selector"
- return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)];
- #pragma clang diagnostic pop
- }
- @interface _YYWebImageApplicationNetworkIndicatorInfo : NSObject
- @property (nonatomic, assign) NSInteger count;
- @property (nonatomic, strong) NSTimer *timer;
- @end
- @implementation _YYWebImageApplicationNetworkIndicatorInfo
- @end
- @implementation YYWebImageManager
- + (instancetype)sharedManager {
- static YYWebImageManager *manager;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- YYImageCache *cache = [YYImageCache sharedCache];
- NSOperationQueue *queue = [NSOperationQueue new];
- if ([queue respondsToSelector:@selector(setQualityOfService:)]) {
- queue.qualityOfService = NSQualityOfServiceBackground;
- }
- manager = [[self alloc] initWithCache:cache queue:queue];
- });
- return manager;
- }
- - (instancetype)init {
- @throw [NSException exceptionWithName:@"YYWebImageManager init error" reason:@"Use the designated initializer to init." userInfo:nil];
- return [self initWithCache:nil queue:nil];
- }
- - (instancetype)initWithCache:(YYImageCache *)cache queue:(NSOperationQueue *)queue{
- self = [super init];
- if (!self) return nil;
- _cache = cache;
- _queue = queue;
- _timeout = 15.0;
- if (YYImageWebPAvailable()) {
- _headers = @{ @"Accept" : @"image/webp,image/*;q=0.8" };
- } else {
- _headers = @{ @"Accept" : @"image/*;q=0.8" };
- }
- return self;
- }
- - (YYWebImageOperation *)requestImageWithURL:(NSURL *)url
- options:(YYWebImageOptions)options
- progress:(YYWebImageProgressBlock)progress
- transform:(YYWebImageTransformBlock)transform
- completion:(YYWebImageCompletionBlock)completion {
-
- NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
- request.timeoutInterval = _timeout;
- request.HTTPShouldHandleCookies = (options & YYWebImageOptionHandleCookies) != 0;
- request.allHTTPHeaderFields = [self headersForURL:url];
- request.HTTPShouldUsePipelining = YES;
- request.cachePolicy = (options & YYWebImageOptionUseNSURLCache) ?
- NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
-
- YYWebImageOperation *operation = [[YYWebImageOperation alloc] initWithRequest:request
- options:options
- cache:_cache
- cacheKey:[self cacheKeyForURL:url]
- progress:progress
- transform:transform ? transform : _sharedTransformBlock
- completion:completion];
- if (_username && _password) {
- operation.credential = [NSURLCredential credentialWithUser:_username password:_password persistence:NSURLCredentialPersistenceForSession];
- }
- if (operation) {
- NSOperationQueue *queue = _queue;
- if (queue) {
- [queue addOperation:operation];
- } else {
- [operation start];
- }
- }
- return operation;
- }
- - (NSDictionary *)headersForURL:(NSURL *)url {
- if (!url) return nil;
- return _headersFilter ? _headersFilter(url, _headers) : _headers;
- }
- - (NSString *)cacheKeyForURL:(NSURL *)url {
- if (!url) return nil;
- return _cacheKeyFilter ? _cacheKeyFilter(url) : url.absoluteString;
- }
- #pragma mark Network Indicator
- + (_YYWebImageApplicationNetworkIndicatorInfo *)_networkIndicatorInfo {
- return objc_getAssociatedObject(self, @selector(_networkIndicatorInfo));
- }
- + (void)_setNetworkIndicatorInfo:(_YYWebImageApplicationNetworkIndicatorInfo *)info {
- objc_setAssociatedObject(self, @selector(_networkIndicatorInfo), info, OBJC_ASSOCIATION_RETAIN);
- }
- + (void)_delaySetActivity:(NSTimer *)timer {
- UIApplication *app = _YYSharedApplication();
- if (!app) return;
-
- NSNumber *visiable = timer.userInfo;
- if (app.networkActivityIndicatorVisible != visiable.boolValue) {
- [app setNetworkActivityIndicatorVisible:visiable.boolValue];
- }
- [timer invalidate];
- }
- + (void)_changeNetworkActivityCount:(NSInteger)delta {
- if (!_YYSharedApplication()) return;
-
- void (^block)() = ^{
- _YYWebImageApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo];
- if (!info) {
- info = [_YYWebImageApplicationNetworkIndicatorInfo new];
- [self _setNetworkIndicatorInfo:info];
- }
- NSInteger count = info.count;
- count += delta;
- info.count = count;
- [info.timer invalidate];
- info.timer = [NSTimer timerWithTimeInterval:kNetworkIndicatorDelay target:self selector:@selector(_delaySetActivity:) userInfo:@(info.count > 0) repeats:NO];
- [[NSRunLoop mainRunLoop] addTimer:info.timer forMode:NSRunLoopCommonModes];
- };
- if ([NSThread isMainThread]) {
- block();
- } else {
- dispatch_async(dispatch_get_main_queue(), block);
- }
- }
- + (void)incrementNetworkActivityCount {
- [self _changeNetworkActivityCount:1];
- }
- + (void)decrementNetworkActivityCount {
- [self _changeNetworkActivityCount:-1];
- }
- + (NSInteger)currentNetworkActivityCount {
- _YYWebImageApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo];
- return info.count;
- }
- @end
|