From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001
From: 单军华
Date: Wed, 11 Jul 2018 10:47:42 +0800
Subject: [PATCH] 首次上传

---
 screendisplay/Pods/SDWebImage/SDWebImage/SDWebImageManager.m |  366 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 366 insertions(+), 0 deletions(-)

diff --git a/screendisplay/Pods/SDWebImage/SDWebImage/SDWebImageManager.m b/screendisplay/Pods/SDWebImage/SDWebImage/SDWebImageManager.m
new file mode 100644
index 0000000..fa529e7
--- /dev/null
+++ b/screendisplay/Pods/SDWebImage/SDWebImage/SDWebImageManager.m
@@ -0,0 +1,366 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWebImageManager.h"
+#import "NSImage+WebCache.h"
+#import <objc/message.h>
+
+#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
+#define UNLOCK(lock) dispatch_semaphore_signal(lock);
+
+@interface SDWebImageCombinedOperation : NSObject <SDWebImageOperation>
+
+@property (assign, nonatomic, getter = isCancelled) BOOL cancelled;
+@property (strong, nonatomic, nullable) SDWebImageDownloadToken *downloadToken;
+@property (strong, nonatomic, nullable) NSOperation *cacheOperation;
+@property (weak, nonatomic, nullable) SDWebImageManager *manager;
+
+@end
+
+@interface SDWebImageManager ()
+
+@property (strong, nonatomic, readwrite, nonnull) SDImageCache *imageCache;
+@property (strong, nonatomic, readwrite, nonnull) SDWebImageDownloader *imageDownloader;
+@property (strong, nonatomic, nonnull) NSMutableSet<NSURL *> *failedURLs;
+@property (strong, nonatomic, nonnull) dispatch_semaphore_t failedURLsLock; // a lock to keep the access to `failedURLs` thread-safe
+@property (strong, nonatomic, nonnull) NSMutableArray<SDWebImageCombinedOperation *> *runningOperations;
+@property (strong, nonatomic, nonnull) dispatch_semaphore_t runningOperationsLock; // a lock to keep the access to `runningOperations` thread-safe
+
+@end
+
+@implementation SDWebImageManager
+
++ (nonnull instancetype)sharedManager {
+    static dispatch_once_t once;
+    static id instance;
+    dispatch_once(&once, ^{
+        instance = [self new];
+    });
+    return instance;
+}
+
+- (nonnull instancetype)init {
+    SDImageCache *cache = [SDImageCache sharedImageCache];
+    SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader];
+    return [self initWithCache:cache downloader:downloader];
+}
+
+- (nonnull instancetype)initWithCache:(nonnull SDImageCache *)cache downloader:(nonnull SDWebImageDownloader *)downloader {
+    if ((self = [super init])) {
+        _imageCache = cache;
+        _imageDownloader = downloader;
+        _failedURLs = [NSMutableSet new];
+        _failedURLsLock = dispatch_semaphore_create(1);
+        _runningOperations = [NSMutableArray new];
+        _runningOperationsLock = dispatch_semaphore_create(1);
+    }
+    return self;
+}
+
+- (nullable NSString *)cacheKeyForURL:(nullable NSURL *)url {
+    if (!url) {
+        return @"";
+    }
+
+    if (self.cacheKeyFilter) {
+        return self.cacheKeyFilter(url);
+    } else {
+        return url.absoluteString;
+    }
+}
+
+- (nullable UIImage *)scaledImageForKey:(nullable NSString *)key image:(nullable UIImage *)image {
+    return SDScaledImageForKey(key, image);
+}
+
+- (void)cachedImageExistsForURL:(nullable NSURL *)url
+                     completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock {
+    NSString *key = [self cacheKeyForURL:url];
+    
+    BOOL isInMemoryCache = ([self.imageCache imageFromMemoryCacheForKey:key] != nil);
+    
+    if (isInMemoryCache) {
+        // making sure we call the completion block on the main queue
+        dispatch_async(dispatch_get_main_queue(), ^{
+            if (completionBlock) {
+                completionBlock(YES);
+            }
+        });
+        return;
+    }
+    
+    [self.imageCache diskImageExistsWithKey:key completion:^(BOOL isInDiskCache) {
+        // the completion block of checkDiskCacheForImageWithKey:completion: is always called on the main queue, no need to further dispatch
+        if (completionBlock) {
+            completionBlock(isInDiskCache);
+        }
+    }];
+}
+
+- (void)diskImageExistsForURL:(nullable NSURL *)url
+                   completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock {
+    NSString *key = [self cacheKeyForURL:url];
+    
+    [self.imageCache diskImageExistsWithKey:key completion:^(BOOL isInDiskCache) {
+        // the completion block of checkDiskCacheForImageWithKey:completion: is always called on the main queue, no need to further dispatch
+        if (completionBlock) {
+            completionBlock(isInDiskCache);
+        }
+    }];
+}
+
+- (id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
+                                     options:(SDWebImageOptions)options
+                                    progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
+                                   completed:(nullable SDInternalCompletionBlock)completedBlock {
+    // Invoking this method without a completedBlock is pointless
+    NSAssert(completedBlock != nil, @"If you mean to prefetch the image, use -[SDWebImagePrefetcher prefetchURLs] instead");
+
+    // Very common mistake is to send the URL using NSString object instead of NSURL. For some strange reason, Xcode won't
+    // throw any warning for this type mismatch. Here we failsafe this error by allowing URLs to be passed as NSString.
+    if ([url isKindOfClass:NSString.class]) {
+        url = [NSURL URLWithString:(NSString *)url];
+    }
+
+    // Prevents app crashing on argument type error like sending NSNull instead of NSURL
+    if (![url isKindOfClass:NSURL.class]) {
+        url = nil;
+    }
+
+    SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new];
+    operation.manager = self;
+
+    BOOL isFailedUrl = NO;
+    if (url) {
+        LOCK(self.failedURLsLock);
+        isFailedUrl = [self.failedURLs containsObject:url];
+        UNLOCK(self.failedURLsLock);
+    }
+
+    if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {
+        [self callCompletionBlockForOperation:operation completion:completedBlock error:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil] url:url];
+        return operation;
+    }
+
+    LOCK(self.runningOperationsLock);
+    [self.runningOperations addObject:operation];
+    UNLOCK(self.runningOperationsLock);
+    NSString *key = [self cacheKeyForURL:url];
+    
+    SDImageCacheOptions cacheOptions = 0;
+    if (options & SDWebImageQueryDataWhenInMemory) cacheOptions |= SDImageCacheQueryDataWhenInMemory;
+    if (options & SDWebImageQueryDiskSync) cacheOptions |= SDImageCacheQueryDiskSync;
+    if (options & SDWebImageScaleDownLargeImages) cacheOptions |= SDImageCacheScaleDownLargeImages;
+    
+    __weak SDWebImageCombinedOperation *weakOperation = operation;
+    operation.cacheOperation = [self.imageCache queryCacheOperationForKey:key options:cacheOptions done:^(UIImage *cachedImage, NSData *cachedData, SDImageCacheType cacheType) {
+        __strong __typeof(weakOperation) strongOperation = weakOperation;
+        if (!strongOperation || strongOperation.isCancelled) {
+            [self safelyRemoveOperationFromRunning:strongOperation];
+            return;
+        }
+        
+        // Check whether we should download image from network
+        BOOL shouldDownload = (!(options & SDWebImageFromCacheOnly))
+            && (!cachedImage || options & SDWebImageRefreshCached)
+            && (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url]);
+        if (shouldDownload) {
+            if (cachedImage && options & SDWebImageRefreshCached) {
+                // If image was found in the cache but SDWebImageRefreshCached is provided, notify about the cached image
+                // AND try to re-download it in order to let a chance to NSURLCache to refresh it from server.
+                [self callCompletionBlockForOperation:strongOperation completion:completedBlock image:cachedImage data:cachedData error:nil cacheType:cacheType finished:YES url:url];
+            }
+
+            // download if no image or requested to refresh anyway, and download allowed by delegate
+            SDWebImageDownloaderOptions downloaderOptions = 0;
+            if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority;
+            if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload;
+            if (options & SDWebImageRefreshCached) downloaderOptions |= SDWebImageDownloaderUseNSURLCache;
+            if (options & SDWebImageContinueInBackground) downloaderOptions |= SDWebImageDownloaderContinueInBackground;
+            if (options & SDWebImageHandleCookies) downloaderOptions |= SDWebImageDownloaderHandleCookies;
+            if (options & SDWebImageAllowInvalidSSLCertificates) downloaderOptions |= SDWebImageDownloaderAllowInvalidSSLCertificates;
+            if (options & SDWebImageHighPriority) downloaderOptions |= SDWebImageDownloaderHighPriority;
+            if (options & SDWebImageScaleDownLargeImages) downloaderOptions |= SDWebImageDownloaderScaleDownLargeImages;
+            
+            if (cachedImage && options & SDWebImageRefreshCached) {
+                // force progressive off if image already cached but forced refreshing
+                downloaderOptions &= ~SDWebImageDownloaderProgressiveDownload;
+                // ignore image read from NSURLCache if image if cached but force refreshing
+                downloaderOptions |= SDWebImageDownloaderIgnoreCachedResponse;
+            }
+            
+            // `SDWebImageCombinedOperation` -> `SDWebImageDownloadToken` -> `downloadOperationCancelToken`, which is a `SDCallbacksDictionary` and retain the completed block below, so we need weak-strong again to avoid retain cycle
+            __weak typeof(strongOperation) weakSubOperation = strongOperation;
+            strongOperation.downloadToken = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *downloadedData, NSError *error, BOOL finished) {
+                __strong typeof(weakSubOperation) strongSubOperation = weakSubOperation;
+                if (!strongSubOperation || strongSubOperation.isCancelled) {
+                    // Do nothing if the operation was cancelled
+                    // See #699 for more details
+                    // if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data
+                } else if (error) {
+                    [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock error:error url:url];
+                    BOOL shouldBlockFailedURL;
+                    // Check whether we should block failed url
+                    if ([self.delegate respondsToSelector:@selector(imageManager:shouldBlockFailedURL:withError:)]) {
+                        shouldBlockFailedURL = [self.delegate imageManager:self shouldBlockFailedURL:url withError:error];
+                    } else {
+                        shouldBlockFailedURL = (   error.code != NSURLErrorNotConnectedToInternet
+                                                && error.code != NSURLErrorCancelled
+                                                && error.code != NSURLErrorTimedOut
+                                                && error.code != NSURLErrorInternationalRoamingOff
+                                                && error.code != NSURLErrorDataNotAllowed
+                                                && error.code != NSURLErrorCannotFindHost
+                                                && error.code != NSURLErrorCannotConnectToHost
+                                                && error.code != NSURLErrorNetworkConnectionLost);
+                    }
+                    
+                    if (shouldBlockFailedURL) {
+                        LOCK(self.failedURLsLock);
+                        [self.failedURLs addObject:url];
+                        UNLOCK(self.failedURLsLock);
+                    }
+                }
+                else {
+                    if ((options & SDWebImageRetryFailed)) {
+                        LOCK(self.failedURLsLock);
+                        [self.failedURLs removeObject:url];
+                        UNLOCK(self.failedURLsLock);
+                    }
+                    
+                    BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly);
+                    
+                    // We've done the scale process in SDWebImageDownloader with the shared manager, this is used for custom manager and avoid extra scale.
+                    if (self != [SDWebImageManager sharedManager] && self.cacheKeyFilter && downloadedImage) {
+                        downloadedImage = [self scaledImageForKey:key image:downloadedImage];
+                    }
+
+                    if (options & SDWebImageRefreshCached && cachedImage && !downloadedImage) {
+                        // Image refresh hit the NSURLCache cache, do not call the completion block
+                    } else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) {
+                        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
+                            UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
+
+                            if (transformedImage && finished) {
+                                BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
+                                NSData *cacheData;
+                                // pass nil if the image was transformed, so we can recalculate the data from the image
+                                if (self.cacheSerializer) {
+                                    cacheData = self.cacheSerializer(transformedImage, (imageWasTransformed ? nil : downloadedData), url);
+                                } else {
+                                    cacheData = (imageWasTransformed ? nil : downloadedData);
+                                }
+                                [self.imageCache storeImage:transformedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
+                            }
+                            
+                            [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:transformedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
+                        });
+                    } else {
+                        if (downloadedImage && finished) {
+                            if (self.cacheSerializer) {
+                                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
+                                    NSData *cacheData = self.cacheSerializer(downloadedImage, downloadedData, url);
+                                    [self.imageCache storeImage:downloadedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
+                                });
+                            } else {
+                                [self.imageCache storeImage:downloadedImage imageData:downloadedData forKey:key toDisk:cacheOnDisk completion:nil];
+                            }
+                        }
+                        [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:downloadedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];
+                    }
+                }
+
+                if (finished) {
+                    [self safelyRemoveOperationFromRunning:strongSubOperation];
+                }
+            }];
+        } else if (cachedImage) {
+            [self callCompletionBlockForOperation:strongOperation completion:completedBlock image:cachedImage data:cachedData error:nil cacheType:cacheType finished:YES url:url];
+            [self safelyRemoveOperationFromRunning:strongOperation];
+        } else {
+            // Image not in cache and download disallowed by delegate
+            [self callCompletionBlockForOperation:strongOperation completion:completedBlock image:nil data:nil error:nil cacheType:SDImageCacheTypeNone finished:YES url:url];
+            [self safelyRemoveOperationFromRunning:strongOperation];
+        }
+    }];
+
+    return operation;
+}
+
+- (void)saveImageToCache:(nullable UIImage *)image forURL:(nullable NSURL *)url {
+    if (image && url) {
+        NSString *key = [self cacheKeyForURL:url];
+        [self.imageCache storeImage:image forKey:key toDisk:YES completion:nil];
+    }
+}
+
+- (void)cancelAll {
+    LOCK(self.runningOperationsLock);
+    NSArray<SDWebImageCombinedOperation *> *copiedOperations = [self.runningOperations copy];
+    UNLOCK(self.runningOperationsLock);
+    [copiedOperations makeObjectsPerformSelector:@selector(cancel)]; // This will call `safelyRemoveOperationFromRunning:` and remove from the array
+}
+
+- (BOOL)isRunning {
+    BOOL isRunning = NO;
+    LOCK(self.runningOperationsLock);
+    isRunning = (self.runningOperations.count > 0);
+    UNLOCK(self.runningOperationsLock);
+    return isRunning;
+}
+
+- (void)safelyRemoveOperationFromRunning:(nullable SDWebImageCombinedOperation*)operation {
+    if (!operation) {
+        return;
+    }
+    LOCK(self.runningOperationsLock);
+    [self.runningOperations removeObject:operation];
+    UNLOCK(self.runningOperationsLock);
+}
+
+- (void)callCompletionBlockForOperation:(nullable SDWebImageCombinedOperation*)operation
+                             completion:(nullable SDInternalCompletionBlock)completionBlock
+                                  error:(nullable NSError *)error
+                                    url:(nullable NSURL *)url {
+    [self callCompletionBlockForOperation:operation completion:completionBlock image:nil data:nil error:error cacheType:SDImageCacheTypeNone finished:YES url:url];
+}
+
+- (void)callCompletionBlockForOperation:(nullable SDWebImageCombinedOperation*)operation
+                             completion:(nullable SDInternalCompletionBlock)completionBlock
+                                  image:(nullable UIImage *)image
+                                   data:(nullable NSData *)data
+                                  error:(nullable NSError *)error
+                              cacheType:(SDImageCacheType)cacheType
+                               finished:(BOOL)finished
+                                    url:(nullable NSURL *)url {
+    dispatch_main_async_safe(^{
+        if (operation && !operation.isCancelled && completionBlock) {
+            completionBlock(image, data, error, cacheType, finished, url);
+        }
+    });
+}
+
+@end
+
+
+@implementation SDWebImageCombinedOperation
+
+- (void)cancel {
+    @synchronized(self) {
+        self.cancelled = YES;
+        if (self.cacheOperation) {
+            [self.cacheOperation cancel];
+            self.cacheOperation = nil;
+        }
+        if (self.downloadToken) {
+            [self.manager.imageDownloader cancel:self.downloadToken];
+        }
+        [self.manager safelyRemoveOperationFromRunning:self];
+    }
+}
+
+@end

--
Gitblit v1.8.0