Commit 00cc824399ac6138289af1afc5f399f26d755c75
0 parents
no message
Showing
16 changed files
with
984 additions
and
0 deletions
CNLiveImageCache.h
0 → 100644
| 1 | +++ a/CNLiveImageCache.h | |
| 1 | +// | |
| 2 | +// CNLiveImageCache.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/19. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | +#import <UIKit/UIKit.h> | |
| 11 | +#import "CNLiveWebImageBlock.h" | |
| 12 | + | |
| 13 | +//typedef void(^CNLiveWebImageQueryCompletedBlock)(UIImage *image, CNLiveImageCacheType type); | |
| 14 | +typedef void(^CNLiveCompletedBlock)(); | |
| 15 | + | |
| 16 | +@interface CNLiveImageCache : NSObject | |
| 17 | + | |
| 18 | ++ (CNLiveImageCache *)sharedImageCache; | |
| 19 | + | |
| 20 | +- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk; | |
| 21 | + | |
| 22 | +- (UIImage *)imageFromMemoryCacheForKey:(NSString *)key; | |
| 23 | + | |
| 24 | +- (UIImage *)imageFromDiskCacheForKey:(NSString *)key; | |
| 25 | + | |
| 26 | +- (BOOL)queryDiskCacheForKey:(NSString *)key done:(CNLiveWebImageQueryCompletedBlock)doneBlock; | |
| 27 | + | |
| 28 | +- (void)removeCacheForKey:(NSString *)key done:(CNLiveCompletedBlock)completed; | |
| 29 | + | |
| 30 | +- (long long)diskCacheSize; | |
| 31 | + | |
| 32 | +- (void)clearMemory; | |
| 33 | + | |
| 34 | +- (void)clearDisk; | |
| 35 | + | |
| 36 | +@end | ... | ... |
CNLiveImageCache.m
0 → 100644
| 1 | +++ a/CNLiveImageCache.m | |
| 1 | +// | |
| 2 | +// CNLiveImageCache.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/19. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "CNLiveImageCache.h" | |
| 10 | +#import <CommonCrypto/CommonDigest.h> | |
| 11 | +#import "UIImage+MultiFormat.h" | |
| 12 | + | |
| 13 | +FOUNDATION_STATIC_INLINE NSUInteger CNLiveCacheCostForImage(UIImage *image) { | |
| 14 | + return image.size.height * image.size.width * image.scale * image.scale; | |
| 15 | +} | |
| 16 | + | |
| 17 | +typedef void(^CNLiveWebImageNoParamsBlock)(); | |
| 18 | + | |
| 19 | +@interface CNLiveImageCache () | |
| 20 | + | |
| 21 | +@property (nonatomic, strong) NSCache *memoryCache; | |
| 22 | +@property (nonatomic, copy) NSString *diskCachePath; | |
| 23 | +@property (nonatomic, strong) dispatch_queue_t ioQueue; | |
| 24 | + | |
| 25 | +@end | |
| 26 | + | |
| 27 | +@implementation CNLiveImageCache | |
| 28 | +{ | |
| 29 | + NSFileManager *_fileManager; | |
| 30 | +} | |
| 31 | + | |
| 32 | ++ (CNLiveImageCache *)sharedImageCache | |
| 33 | +{ | |
| 34 | + static dispatch_once_t onceToken; | |
| 35 | + static id instance; | |
| 36 | + dispatch_once(&onceToken, ^{ | |
| 37 | + instance = [self new]; | |
| 38 | + }); | |
| 39 | + return instance; | |
| 40 | +} | |
| 41 | + | |
| 42 | +- (id)init { | |
| 43 | + return [self initWithNamespace:@"default"]; | |
| 44 | +} | |
| 45 | + | |
| 46 | +- (id)initWithNamespace:(NSString *)ns { | |
| 47 | + NSString *path = [self makeDiskCachePath:ns]; | |
| 48 | + return [self initWithNamespace:ns diskCacheDirectory:path]; | |
| 49 | +} | |
| 50 | + | |
| 51 | +- (NSString *)makeDiskCachePath:(NSString *)fullNamespace { | |
| 52 | + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); | |
| 53 | + return [paths[0] stringByAppendingString:fullNamespace]; | |
| 54 | +} | |
| 55 | + | |
| 56 | +- (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory { | |
| 57 | + if (self = [super init]) { | |
| 58 | + NSString *fullNameSpace = [@"com.cnlive.CNLiveImageCache." stringByAppendingString:ns]; | |
| 59 | + _ioQueue = dispatch_queue_create("com.cnlive.CNLiveImageCacheQueue", DISPATCH_QUEUE_SERIAL); | |
| 60 | + _memoryCache = [[NSCache alloc] init]; | |
| 61 | + _memoryCache.name = fullNameSpace; | |
| 62 | + | |
| 63 | + if (directory != nil) { | |
| 64 | + _diskCachePath = [directory stringByAppendingPathComponent:fullNameSpace]; | |
| 65 | + } | |
| 66 | + else { | |
| 67 | + _diskCachePath = [[self makeDiskCachePath:ns] stringByAppendingPathComponent:fullNameSpace]; | |
| 68 | + } | |
| 69 | + | |
| 70 | + dispatch_sync(_ioQueue, ^{ | |
| 71 | + _fileManager = [NSFileManager new]; | |
| 72 | + }); | |
| 73 | + | |
| 74 | + [[NSNotificationCenter defaultCenter] addObserver:self | |
| 75 | + selector:@selector(clearMemory) | |
| 76 | + name:UIApplicationDidReceiveMemoryWarningNotification | |
| 77 | + object:nil]; | |
| 78 | + | |
| 79 | +// [[NSNotificationCenter defaultCenter] addObserver:self | |
| 80 | +// selector:@selector(clearDisk) | |
| 81 | +// name:UIApplicationWillTerminateNotification | |
| 82 | +// object:nil]; | |
| 83 | + } | |
| 84 | + return self; | |
| 85 | +} | |
| 86 | + | |
| 87 | +- (void)dealloc | |
| 88 | +{ | |
| 89 | + [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
| 90 | +} | |
| 91 | + | |
| 92 | +- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk | |
| 93 | +{ | |
| 94 | + if (!image || !key) { | |
| 95 | + return; | |
| 96 | + } | |
| 97 | + | |
| 98 | + NSUInteger cost = CNLiveCacheCostForImage(image); | |
| 99 | + [_memoryCache setObject:image forKey:key cost:cost]; | |
| 100 | + | |
| 101 | + if (toDisk) { | |
| 102 | + dispatch_async(_ioQueue, ^{ | |
| 103 | + NSData *data = UIImageJPEGRepresentation(image, 1.0); | |
| 104 | + | |
| 105 | + if (data) { | |
| 106 | + if (![_fileManager fileExistsAtPath:_diskCachePath]) { | |
| 107 | + [_fileManager createDirectoryAtPath:_diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; | |
| 108 | + } | |
| 109 | + NSString *cachePathForKey = [self defaultCachePathForKey:key]; | |
| 110 | + [_fileManager createFileAtPath:cachePathForKey contents:data attributes:nil]; | |
| 111 | + } | |
| 112 | + }); | |
| 113 | + } | |
| 114 | +} | |
| 115 | + | |
| 116 | +- (UIImage *)imageFromMemoryCacheForKey:(NSString *)key | |
| 117 | +{ | |
| 118 | + return [self.memoryCache objectForKey:key]; | |
| 119 | +} | |
| 120 | + | |
| 121 | +- (UIImage *)imageFromDiskCacheForKey:(NSString *)key | |
| 122 | +{ | |
| 123 | + UIImage *memoryImage = [self imageFromMemoryCacheForKey:key]; | |
| 124 | + if (memoryImage) { | |
| 125 | + return memoryImage; | |
| 126 | + } | |
| 127 | + | |
| 128 | + NSData *diskData = [self getDiskImageDataWithKey:key]; | |
| 129 | + if (diskData) { | |
| 130 | + return [UIImage ws_imageWithData:diskData]; | |
| 131 | + } | |
| 132 | + | |
| 133 | + return nil; | |
| 134 | +} | |
| 135 | + | |
| 136 | +- (BOOL)queryDiskCacheForKey:(NSString *)key done:(CNLiveWebImageQueryCompletedBlock)doneBlock | |
| 137 | +{ | |
| 138 | + if (!doneBlock) { | |
| 139 | + return NO; | |
| 140 | + } | |
| 141 | + if (!key) { | |
| 142 | + doneBlock(nil, CNLiveImageCacheTypeNone); | |
| 143 | + return NO; | |
| 144 | + } | |
| 145 | + | |
| 146 | + UIImage *memoryImage = [self imageFromMemoryCacheForKey:key]; | |
| 147 | + if (memoryImage) { | |
| 148 | + doneBlock(memoryImage, CNLiveImageCacheTypeMemory); | |
| 149 | + return YES; | |
| 150 | + } | |
| 151 | + | |
| 152 | + UIImage *diskImage = [self imageFromDiskCacheForKey:key]; | |
| 153 | + if (diskImage) { | |
| 154 | + doneBlock(diskImage, CNLiveImageCacheTypeDisk); | |
| 155 | + return YES; | |
| 156 | + } | |
| 157 | + | |
| 158 | + doneBlock(nil, CNLiveImageCacheTypeNone); | |
| 159 | + return NO; | |
| 160 | + | |
| 161 | +} | |
| 162 | + | |
| 163 | +- (void)removeCacheForKey:(NSString *)key done:(CNLiveCompletedBlock)completed | |
| 164 | +{ | |
| 165 | + if (!key || !completed) { | |
| 166 | + return; | |
| 167 | + } | |
| 168 | + | |
| 169 | + if ([self imageFromMemoryCacheForKey:key]) { | |
| 170 | + [self.memoryCache removeObjectForKey:key]; | |
| 171 | + } | |
| 172 | + | |
| 173 | + if ([self imageFromDiskCacheForKey:key]) { | |
| 174 | + NSString *cachePathForKey = [self defaultCachePathForKey:key]; | |
| 175 | + [_fileManager removeItemAtPath:cachePathForKey error:nil]; | |
| 176 | + } | |
| 177 | + | |
| 178 | + completed(); | |
| 179 | +} | |
| 180 | + | |
| 181 | +- (long long)diskCacheSize | |
| 182 | +{ | |
| 183 | + if ([_fileManager fileExistsAtPath:self.diskCachePath]) { | |
| 184 | + NSArray *subPathArray = [_fileManager subpathsAtPath:self.diskCachePath]; | |
| 185 | + if (subPathArray && subPathArray.count > 0) { | |
| 186 | + long long totalCacheSize = 0; | |
| 187 | + for (NSString *subPath in subPathArray) { | |
| 188 | + NSString *fullPath = [self.diskCachePath stringByAppendingPathComponent:subPath]; | |
| 189 | + NSDictionary *cacheSizeDic = [_fileManager attributesOfItemAtPath:fullPath error:nil]; | |
| 190 | + totalCacheSize += [cacheSizeDic fileSize]; | |
| 191 | + } | |
| 192 | + return totalCacheSize; | |
| 193 | + } | |
| 194 | + } | |
| 195 | + return 0; | |
| 196 | +} | |
| 197 | + | |
| 198 | +- (void)clearMemory | |
| 199 | +{ | |
| 200 | + [self.memoryCache removeAllObjects]; | |
| 201 | +} | |
| 202 | + | |
| 203 | +- (void)clearDisk | |
| 204 | +{ | |
| 205 | + [self clearDiskOnCompletion:nil]; | |
| 206 | +} | |
| 207 | + | |
| 208 | +- (void)clearDiskOnCompletion:(CNLiveWebImageNoParamsBlock)completion | |
| 209 | +{ | |
| 210 | + dispatch_async(self.ioQueue, ^{ | |
| 211 | + [_fileManager removeItemAtPath:self.diskCachePath error:nil]; | |
| 212 | + [_fileManager createDirectoryAtPath:self.diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL]; | |
| 213 | + | |
| 214 | + if (completion) { | |
| 215 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 216 | + completion(); | |
| 217 | + }); | |
| 218 | + } | |
| 219 | + }); | |
| 220 | +} | |
| 221 | + | |
| 222 | +#pragma mark <PrivateMethod> | |
| 223 | +- (NSData *)getDiskImageDataWithKey:(NSString *)key | |
| 224 | +{ | |
| 225 | + NSString *filePath = [self defaultCachePathForKey:key]; | |
| 226 | + NSData *imageData = [NSData dataWithContentsOfFile:filePath]; | |
| 227 | + return imageData; | |
| 228 | +} | |
| 229 | + | |
| 230 | +- (NSString *)defaultCachePathForKey:(NSString *)key | |
| 231 | +{ | |
| 232 | + return [self cachePathForKey:key inPath:self.diskCachePath]; | |
| 233 | +} | |
| 234 | + | |
| 235 | +- (NSString *)cachePathForKey:(NSString *)key inPath:(NSString *)path | |
| 236 | +{ | |
| 237 | + NSString *fileName = [self cachedFileNameForKey:key]; | |
| 238 | + return [path stringByAppendingPathComponent:fileName]; | |
| 239 | +} | |
| 240 | + | |
| 241 | +- (NSString *)cachedFileNameForKey:(NSString *)key { | |
| 242 | + const char *str = [key UTF8String]; | |
| 243 | + if (str == NULL) { | |
| 244 | + str = ""; | |
| 245 | + } | |
| 246 | + unsigned char r[CC_MD5_DIGEST_LENGTH]; | |
| 247 | + CC_MD5(str, (CC_LONG)strlen(str), r); | |
| 248 | + NSString *filename = [NSString stringWithFormat:@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", | |
| 249 | + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15]]; | |
| 250 | + | |
| 251 | + return filename; | |
| 252 | +} | |
| 253 | + | |
| 254 | +@end | ... | ... |
CNLiveWebImageBlock.h
0 → 100644
| 1 | +++ a/CNLiveWebImageBlock.h | |
| 1 | +// | |
| 2 | +// CNLiveWebImageBlock.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/27. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#ifndef CNLiveWebImageBlock_h | |
| 10 | +#define CNLiveWebImageBlock_h | |
| 11 | + | |
| 12 | +typedef NS_ENUM(NSUInteger, CNLiveImageCacheType) { | |
| 13 | + CNLiveImageCacheTypeNone, | |
| 14 | + CNLiveImageCacheTypeMemory, | |
| 15 | + CNLiveImageCacheTypeDisk | |
| 16 | +}; | |
| 17 | + | |
| 18 | +typedef void(^CNLiveDownloadProgressBlock)(NSInteger receivedSize, NSInteger expectedSize); | |
| 19 | +typedef void(^CNLiveDownloadCompletedBlock)(UIImage *image, NSData *data, NSError *error, BOOL finished); | |
| 20 | + | |
| 21 | +typedef void(^CNLiveWebImageQueryCompletedBlock)(UIImage *image, CNLiveImageCacheType type); | |
| 22 | +typedef void(^CNLiveCompletedBlock)(); | |
| 23 | +typedef void(^CNLiveWebImageNoParamsBlock)(); | |
| 24 | + | |
| 25 | +#endif /* CNLiveWebImageBlock_h */ | ... | ... |
CNLiveWebImageDownload.h
0 → 100644
| 1 | +++ a/CNLiveWebImageDownload.h | |
| 1 | +// | |
| 2 | +// CNLiveWebImageDownload.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/14. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | +#import <UIKit/UIKit.h> | |
| 11 | +#import "CNLiveWebImageOperation.h" | |
| 12 | +#import "CNLiveWebImageBlock.h" | |
| 13 | + | |
| 14 | +typedef NS_OPTIONS(NSUInteger, CNLiveWebImageDownloadOptions) { | |
| 15 | + CNLiveWebImageDownloadProgressiveDownload = 1 << 0, | |
| 16 | + CNLiveWebImageDownloadContinueInBackground = 1 << 1 | |
| 17 | +}; | |
| 18 | + | |
| 19 | +@interface CNLiveWebImageDownload : NSObject | |
| 20 | + | |
| 21 | ++ (CNLiveWebImageDownload *)sharedDownload; | |
| 22 | + | |
| 23 | +- (id <CNLiveWebImageOperation>)downloadWebImageWithURL:(NSURL *)url options:(CNLiveWebImageDownloadOptions)options progress:(CNLiveDownloadProgressBlock)progress completed:(CNLiveDownloadCompletedBlock)completed; | |
| 24 | + | |
| 25 | +@end | ... | ... |
CNLiveWebImageDownload.m
0 → 100644
| 1 | +++ a/CNLiveWebImageDownload.m | |
| 1 | +// | |
| 2 | +// CNLiveWebImageDownload.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/14. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "CNLiveWebImageDownload.h" | |
| 10 | +#import "CNLiveWebImageDownloadOperation.h" | |
| 11 | + | |
| 12 | +@interface CNLiveWebImageDownload () | |
| 13 | + | |
| 14 | +@property (nonatomic, strong) NSOperationQueue *downloadQueue; | |
| 15 | + | |
| 16 | +@end | |
| 17 | + | |
| 18 | +@implementation CNLiveWebImageDownload | |
| 19 | + | |
| 20 | ++ (CNLiveWebImageDownload *)sharedDownload | |
| 21 | +{ | |
| 22 | + static dispatch_once_t once; | |
| 23 | + static id instance; | |
| 24 | + dispatch_once(&once, ^{ | |
| 25 | + instance = [self new]; | |
| 26 | + }); | |
| 27 | + return instance; | |
| 28 | +} | |
| 29 | + | |
| 30 | +- (instancetype)init | |
| 31 | +{ | |
| 32 | + if ((self = [super init])) { | |
| 33 | + _downloadQueue = [NSOperationQueue new]; | |
| 34 | + _downloadQueue.maxConcurrentOperationCount = 6; | |
| 35 | + } | |
| 36 | + return self; | |
| 37 | +} | |
| 38 | + | |
| 39 | +- (void)dealloc | |
| 40 | +{ | |
| 41 | + [self.downloadQueue cancelAllOperations]; | |
| 42 | +} | |
| 43 | + | |
| 44 | +- (id<CNLiveWebImageOperation>)downloadWebImageWithURL:(NSURL *)url options:(CNLiveWebImageDownloadOptions)options progress:(CNLiveDownloadProgressBlock)progress completed:(CNLiveDownloadCompletedBlock)completed | |
| 45 | +{ | |
| 46 | + CNLiveWebImageDownloadOperation *operation; | |
| 47 | + operation = [[CNLiveWebImageDownloadOperation alloc] initWithURL:url | |
| 48 | + options:options | |
| 49 | + progress:progress | |
| 50 | + completed:completed]; | |
| 51 | + [self.downloadQueue addOperation:operation]; | |
| 52 | + return (id <CNLiveWebImageOperation>)operation; | |
| 53 | +} | |
| 54 | +@end | ... | ... |
CNLiveWebImageDownloadOperation.h
0 → 100644
| 1 | +++ a/CNLiveWebImageDownloadOperation.h | |
| 1 | +// | |
| 2 | +// CNLiveWebImageDownloadOperation.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/25. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | +#import "CNLiveWebImageDownload.h" | |
| 11 | +#import "CNLiveWebImageBlock.h" | |
| 12 | + | |
| 13 | +@interface CNLiveWebImageDownloadOperation : NSOperation | |
| 14 | + | |
| 15 | +- (id)initWithURL:(NSURL *)url options:(CNLiveWebImageDownloadOptions)options progress:(CNLiveDownloadProgressBlock)progress completed:(CNLiveDownloadCompletedBlock)completed; | |
| 16 | + | |
| 17 | +@end | ... | ... |
CNLiveWebImageDownloadOperation.m
0 → 100644
| 1 | +++ a/CNLiveWebImageDownloadOperation.m | |
| 1 | +// | |
| 2 | +// CNLiveWebImageDownloadOperation.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/25. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "CNLiveWebImageDownloadOperation.h" | |
| 10 | +#import "CNLiveWebImageOperation.h" | |
| 11 | +#import <ImageIO/ImageIO.h> | |
| 12 | +#import "UIImage+MultiFormat.h" | |
| 13 | + | |
| 14 | +#define CNLiveWebImageBackgroundSessionIdentifier @"CNLiveWebImageBackgroundSessionIdentifier" | |
| 15 | + | |
| 16 | +@interface CNLiveWebImageDownloadOperation ()<CNLiveWebImageOperation, NSURLSessionDataDelegate, NSURLSessionTaskDelegate, NSURLSessionDelegate> | |
| 17 | + | |
| 18 | +@property (nonatomic, copy) CNLiveDownloadProgressBlock progressBlock; | |
| 19 | +@property (nonatomic, copy) CNLiveDownloadCompletedBlock completedBlock; | |
| 20 | +@property (nonatomic, assign) CNLiveWebImageDownloadOptions options; | |
| 21 | +@property (nonatomic, strong) NSURL *url; | |
| 22 | + | |
| 23 | +@property (nonatomic, strong) NSURLSessionConfiguration *config; | |
| 24 | +@property (nonatomic, strong) NSURLSession *session; | |
| 25 | +@property (nonatomic, strong) NSURLSessionDataTask *dataTask; | |
| 26 | +@property (nonatomic, assign) NSInteger expectedSize; | |
| 27 | +@property (nonatomic, strong) NSMutableData *imageData; | |
| 28 | +@property (nonatomic, strong) NSURLResponse *response; | |
| 29 | + | |
| 30 | +@end | |
| 31 | + | |
| 32 | +@implementation CNLiveWebImageDownloadOperation | |
| 33 | + | |
| 34 | +- (id)initWithURL:(NSURL *)url options:(CNLiveWebImageDownloadOptions)options progress:(CNLiveDownloadProgressBlock)progress completed:(CNLiveDownloadCompletedBlock)completed | |
| 35 | +{ | |
| 36 | + if ((self = [super init])) { | |
| 37 | + _url = url; | |
| 38 | + _progressBlock = progress; | |
| 39 | + _completedBlock = completed; | |
| 40 | + _options = options; | |
| 41 | + } | |
| 42 | + return self; | |
| 43 | +} | |
| 44 | + | |
| 45 | +- (void)start | |
| 46 | +{ | |
| 47 | + @synchronized (self) { | |
| 48 | + if (self.isCancelled) { | |
| 49 | + return; | |
| 50 | + } | |
| 51 | + } | |
| 52 | + self.dataTask = [self.session dataTaskWithURL:self.url]; | |
| 53 | + [self.dataTask resume]; | |
| 54 | + [self.session finishTasksAndInvalidate]; | |
| 55 | +} | |
| 56 | + | |
| 57 | +- (NSURLSessionConfiguration *)config | |
| 58 | +{ | |
| 59 | + if (!_config) { | |
| 60 | + if (self.options & CNLiveWebImageDownloadContinueInBackground) { | |
| 61 | + _config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:CNLiveWebImageBackgroundSessionIdentifier]; | |
| 62 | + } | |
| 63 | + else { | |
| 64 | + _config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; | |
| 65 | + } | |
| 66 | + } | |
| 67 | + return _config; | |
| 68 | +} | |
| 69 | + | |
| 70 | +- (NSURLSession *)session | |
| 71 | +{ | |
| 72 | + if (!_session) { | |
| 73 | + _session = [NSURLSession sessionWithConfiguration:self.config delegate:self delegateQueue:[NSOperationQueue mainQueue]]; | |
| 74 | + } | |
| 75 | + return _session; | |
| 76 | +} | |
| 77 | + | |
| 78 | +#pragma mark <NSURLSessionDataDelegate> | |
| 79 | +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler | |
| 80 | +{ | |
| 81 | + if (![response respondsToSelector:@selector(statusCode)] || ([((NSHTTPURLResponse *)response) statusCode] < 400 && [((NSHTTPURLResponse *)response) statusCode] != 304)) { | |
| 82 | + NSInteger expected = response.expectedContentLength > 0 ? (NSInteger)response.expectedContentLength : 0; | |
| 83 | + self.expectedSize = expected; | |
| 84 | + if (self.progressBlock) { | |
| 85 | + self.progressBlock(0, expected); | |
| 86 | + } | |
| 87 | + | |
| 88 | + self.imageData = [[NSMutableData alloc] initWithCapacity:expected]; | |
| 89 | + self.response = response; | |
| 90 | + completionHandler(NSURLSessionResponseAllow); | |
| 91 | + } | |
| 92 | + else { | |
| 93 | + | |
| 94 | + [self.dataTask cancel]; | |
| 95 | + | |
| 96 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 97 | + if (self.completedBlock) { | |
| 98 | + self.completedBlock(nil, nil, [NSError errorWithDomain:NSURLErrorDomain code:[((NSHTTPURLResponse *)response) statusCode] userInfo:nil], YES); | |
| 99 | + } | |
| 100 | + }); | |
| 101 | + } | |
| 102 | +} | |
| 103 | + | |
| 104 | +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data | |
| 105 | +{ | |
| 106 | + [self.imageData appendData:data]; | |
| 107 | + if (self.options & CNLiveWebImageDownloadProgressiveDownload && self.completedBlock) { | |
| 108 | + const NSInteger totalSize = self.imageData.length; | |
| 109 | + CGImageSourceRef imageSource = CGImageSourceCreateWithData((__bridge CFDataRef)self.imageData, NULL); | |
| 110 | + if (totalSize < self.expectedSize) { | |
| 111 | + CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); | |
| 112 | + if (partialImageRef) { | |
| 113 | + UIImage *image = [UIImage imageWithCGImage:partialImageRef]; | |
| 114 | + CGImageRelease(partialImageRef); | |
| 115 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 116 | + if (self.completedBlock) { | |
| 117 | + self.completedBlock(image, self.imageData, nil, NO); | |
| 118 | + } | |
| 119 | + }); | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + CFRelease(imageSource); | |
| 124 | + } | |
| 125 | + | |
| 126 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 127 | + if (self.progressBlock) { | |
| 128 | + self.progressBlock(self.imageData.length, self.expectedSize); | |
| 129 | + } | |
| 130 | + }); | |
| 131 | +} | |
| 132 | + | |
| 133 | +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error | |
| 134 | +{ | |
| 135 | + if (error) { | |
| 136 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 137 | + if (self.completedBlock) { | |
| 138 | + self.completedBlock(nil, nil, error, NO); | |
| 139 | + } | |
| 140 | + }); | |
| 141 | + } | |
| 142 | + else { | |
| 143 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 144 | + if (self.completedBlock) { | |
| 145 | + self.completedBlock([UIImage ws_imageWithData:self.imageData], self.imageData, nil, YES); | |
| 146 | + } | |
| 147 | + }); | |
| 148 | + } | |
| 149 | +} | |
| 150 | + | |
| 151 | +- (void)cancel | |
| 152 | +{ | |
| 153 | + if (self.session) { | |
| 154 | + [self.session invalidateAndCancel]; | |
| 155 | + } | |
| 156 | + self.completedBlock = nil; | |
| 157 | + self.progressBlock = nil; | |
| 158 | + self.session = nil; | |
| 159 | + self.imageData = nil; | |
| 160 | +} | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | +@end | ... | ... |
CNLiveWebImageManager.h
0 → 100644
| 1 | +++ a/CNLiveWebImageManager.h | |
| 1 | +// | |
| 2 | +// CNLiveWebImageManager.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/27. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | +#import <UIKit/UIKit.h> | |
| 11 | +#import "CNLiveWebImageBlock.h" | |
| 12 | +#import "CNLiveWebImageOperation.h" | |
| 13 | + | |
| 14 | +typedef NS_OPTIONS(NSUInteger, CNLiveWebImageOptions) { | |
| 15 | + CNLiveWebImageRetryFailed = 1 << 0, | |
| 16 | + CNLiveWebImageCacheMemoryOnly = 1 << 1, | |
| 17 | + CNLiveWebImageProgressiveDownload = 1 << 2, | |
| 18 | + CNLiveWebImageContinueInBackground = 1 << 3 | |
| 19 | +}; | |
| 20 | + | |
| 21 | +@interface CNLiveWebImageManager : NSObject | |
| 22 | + | |
| 23 | ++ (nonnull id)sharedManager; | |
| 24 | + | |
| 25 | +- (nonnull id <CNLiveWebImageOperation>)downloadWebImageWithURL:(nonnull NSURL *)url options:(CNLiveWebImageOptions)options progress:(nonnull CNLiveDownloadProgressBlock)progress completed:(nonnull CNLiveDownloadCompletedBlock)completed; | |
| 26 | + | |
| 27 | +- (void)storeImage:(nonnull UIImage *)image imageUrl:(nonnull NSURL *)url toDisk:(BOOL)toDisk; | |
| 28 | + | |
| 29 | +- (nullable UIImage *)imageFromMemoryCacheWithImageUrl:(nonnull NSURL *)url; | |
| 30 | + | |
| 31 | +- (nullable UIImage *)imageFromDiskCacheWithImageUrl:(nonnull NSURL *)url; | |
| 32 | + | |
| 33 | +- (BOOL)queryDiskCacheWithImageUrl:(nonnull NSURL *)url done:(nonnull CNLiveWebImageQueryCompletedBlock)doneBlock; | |
| 34 | + | |
| 35 | +- (void)removeCacheWithUrl:(nonnull NSURL *)url done:(nonnull CNLiveCompletedBlock)completed; | |
| 36 | + | |
| 37 | +- (long long)diskCacheSize; | |
| 38 | + | |
| 39 | +- (void)clearMemory; | |
| 40 | + | |
| 41 | +- (void)clearDisk; | |
| 42 | + | |
| 43 | +@end | ... | ... |
CNLiveWebImageManager.m
0 → 100644
| 1 | +++ a/CNLiveWebImageManager.m | |
| 1 | +// | |
| 2 | +// CNLiveWebImageManager.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/27. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "CNLiveWebImageManager.h" | |
| 10 | +#import "CNLiveWebImageDownload.h" | |
| 11 | +#import "CNLiveImageCache.h" | |
| 12 | + | |
| 13 | +@interface CNLiveWebImageManager () | |
| 14 | + | |
| 15 | +@property (nonatomic, strong) CNLiveImageCache *imageCache; | |
| 16 | +@property (nonatomic, strong) NSMutableSet *failedURLs; | |
| 17 | + | |
| 18 | +@end | |
| 19 | + | |
| 20 | +@implementation CNLiveWebImageManager | |
| 21 | + | |
| 22 | ++ (id)sharedManager | |
| 23 | +{ | |
| 24 | + static id manager; | |
| 25 | + static dispatch_once_t once; | |
| 26 | + dispatch_once(&once, ^{ | |
| 27 | + manager = [self new]; | |
| 28 | + }); | |
| 29 | + return manager; | |
| 30 | +} | |
| 31 | + | |
| 32 | +- (instancetype)init | |
| 33 | +{ | |
| 34 | + if ((self = [super init])) { | |
| 35 | + _imageCache = [CNLiveImageCache sharedImageCache]; | |
| 36 | + _failedURLs = [NSMutableSet new]; | |
| 37 | + } | |
| 38 | + return self; | |
| 39 | +} | |
| 40 | + | |
| 41 | +- (id<CNLiveWebImageOperation>)downloadWebImageWithURL:(NSURL *)url options:(CNLiveWebImageOptions)options progress:(CNLiveDownloadProgressBlock)progress completed:(CNLiveDownloadCompletedBlock)completed | |
| 42 | +{ | |
| 43 | + if ([url isKindOfClass:NSString.class]) { | |
| 44 | + url = [NSURL URLWithString:(NSString *)url]; | |
| 45 | + } | |
| 46 | + if (![url isKindOfClass:NSURL.class]) { | |
| 47 | + url = nil; | |
| 48 | + } | |
| 49 | + | |
| 50 | + BOOL isFailedUrl = NO; | |
| 51 | + @synchronized (self.failedURLs) { | |
| 52 | + isFailedUrl = [self.failedURLs containsObject:url]; | |
| 53 | + } | |
| 54 | + if (!url || (!(options & CNLiveWebImageRetryFailed) && isFailedUrl)) { | |
| 55 | + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]; | |
| 56 | + completed(nil, nil, error, YES); | |
| 57 | + } | |
| 58 | + | |
| 59 | + BOOL hasCacheImage = [self.imageCache queryDiskCacheForKey:url.absoluteString done:^(UIImage *image, CNLiveImageCacheType type) { | |
| 60 | + if (image) { | |
| 61 | + completed(image,UIImageJPEGRepresentation(image, 1.0), nil, YES); | |
| 62 | + } | |
| 63 | + }];; | |
| 64 | + | |
| 65 | + if (hasCacheImage) { | |
| 66 | + return nil; | |
| 67 | + } | |
| 68 | + | |
| 69 | + | |
| 70 | + CNLiveWebImageDownloadOptions downloadOptions = 0; | |
| 71 | + if (options & CNLiveWebImageProgressiveDownload) downloadOptions |= CNLiveWebImageDownloadProgressiveDownload; | |
| 72 | + if (options & CNLiveWebImageContinueInBackground) downloadOptions |= CNLiveWebImageDownloadContinueInBackground; | |
| 73 | + id <CNLiveWebImageOperation> operation = [[CNLiveWebImageDownload sharedDownload] downloadWebImageWithURL:url options:downloadOptions progress:progress completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { | |
| 74 | + if (error) { | |
| 75 | + BOOL shouldBeFailedURLAlliOSVersion = (error.code != NSURLErrorNotConnectedToInternet && error.code != NSURLErrorCancelled && error.code != NSURLErrorTimedOut); | |
| 76 | + BOOL shouldBeFailedURLiOS7 = (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1 && error.code != NSURLErrorInternationalRoamingOff && error.code != NSURLErrorCallIsActive && error.code != NSURLErrorDataNotAllowed); | |
| 77 | + if (shouldBeFailedURLAlliOSVersion || shouldBeFailedURLiOS7) { | |
| 78 | + @synchronized (self.failedURLs) { | |
| 79 | + [self.failedURLs addObject:url]; | |
| 80 | + } | |
| 81 | + } | |
| 82 | + } | |
| 83 | + else { | |
| 84 | + if ((options & CNLiveWebImageRetryFailed)) { | |
| 85 | + @synchronized (self.failedURLs) { | |
| 86 | + [self.failedURLs removeObject:url]; | |
| 87 | + } | |
| 88 | + } | |
| 89 | + | |
| 90 | + BOOL cacheOnDisk = !(options & CNLiveWebImageCacheMemoryOnly); | |
| 91 | + if (image && finished) { | |
| 92 | + if (cacheOnDisk) { | |
| 93 | + [self.imageCache storeImage:image forKey:[url absoluteString] toDisk:YES]; | |
| 94 | + } | |
| 95 | + else { | |
| 96 | + [self.imageCache storeImage:image forKey:[url absoluteString] toDisk:NO]; | |
| 97 | + } | |
| 98 | + } | |
| 99 | + | |
| 100 | + completed(image, data, error, finished); | |
| 101 | + } | |
| 102 | + | |
| 103 | + }]; | |
| 104 | + return operation; | |
| 105 | +} | |
| 106 | + | |
| 107 | +- (void)storeImage:(UIImage *)image imageUrl:(NSURL *)url toDisk:(BOOL)toDisk | |
| 108 | +{ | |
| 109 | + [self.imageCache storeImage:image forKey:url.absoluteString toDisk:toDisk]; | |
| 110 | +} | |
| 111 | + | |
| 112 | +- (UIImage *)imageFromMemoryCacheWithImageUrl:(NSURL *)url | |
| 113 | +{ | |
| 114 | + return [self.imageCache imageFromMemoryCacheForKey:url.absoluteString]; | |
| 115 | +} | |
| 116 | + | |
| 117 | +- (UIImage *)imageFromDiskCacheWithImageUrl:(NSURL *)url | |
| 118 | +{ | |
| 119 | + return [self.imageCache imageFromDiskCacheForKey:url.absoluteString]; | |
| 120 | +} | |
| 121 | + | |
| 122 | +- (BOOL)queryDiskCacheWithImageUrl:(NSURL *)url done:(CNLiveWebImageQueryCompletedBlock)doneBlock | |
| 123 | +{ | |
| 124 | + return [self.imageCache queryDiskCacheForKey:url.absoluteString done:doneBlock]; | |
| 125 | +} | |
| 126 | + | |
| 127 | +- (void)removeCacheWithUrl:(NSURL *)url done:(CNLiveCompletedBlock)completed | |
| 128 | +{ | |
| 129 | + [self.imageCache removeCacheForKey:url.absoluteString done:completed]; | |
| 130 | +} | |
| 131 | + | |
| 132 | +- (long long)diskCacheSize | |
| 133 | +{ | |
| 134 | + return [self.imageCache diskCacheSize]; | |
| 135 | +} | |
| 136 | + | |
| 137 | +- (void)clearMemory | |
| 138 | +{ | |
| 139 | + [self.imageCache clearMemory]; | |
| 140 | +} | |
| 141 | + | |
| 142 | +- (void)clearDisk | |
| 143 | +{ | |
| 144 | + [self.imageCache clearDisk]; | |
| 145 | +} | |
| 146 | + | |
| 147 | +@end | ... | ... |
CNLiveWebImageOperation.h
0 → 100644
| 1 | +++ a/CNLiveWebImageOperation.h | |
| 1 | +// | |
| 2 | +// CNLiveWebImageOperation.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/19. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | + | |
| 11 | +@protocol CNLiveWebImageOperation <NSObject> | |
| 12 | + | |
| 13 | +- (void)cancel; | |
| 14 | + | |
| 15 | +@end | ... | ... |
NSData+ImageContentType.h
0 → 100644
| 1 | +++ a/NSData+ImageContentType.h | |
| 1 | +// | |
| 2 | +// NSData+ImageContentType.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/21. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <Foundation/Foundation.h> | |
| 10 | + | |
| 11 | +@interface NSData (ImageContentType) | |
| 12 | + | |
| 13 | ++ (NSString *)ws_imageContentTypeWithData:(NSData *)data; | |
| 14 | + | |
| 15 | +@end | ... | ... |
NSData+ImageContentType.m
0 → 100644
| 1 | +++ a/NSData+ImageContentType.m | |
| 1 | +// | |
| 2 | +// NSData+ImageContentType.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/21. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "NSData+ImageContentType.h" | |
| 10 | + | |
| 11 | +@implementation NSData (ImageContentType) | |
| 12 | + | |
| 13 | ++ (NSString *)ws_imageContentTypeWithData:(NSData *)data | |
| 14 | +{ | |
| 15 | + uint8_t c; | |
| 16 | + [data getBytes:&c length:1]; | |
| 17 | + switch (c) { | |
| 18 | + case 0xFF: | |
| 19 | + return @"image/jpeg"; | |
| 20 | + case 0x89: | |
| 21 | + return @"image/png"; | |
| 22 | + case 0x47: | |
| 23 | + return @"image/gif"; | |
| 24 | + case 0x49: | |
| 25 | + case 0x4D: | |
| 26 | + return @"image/tiff"; | |
| 27 | + case 0x52: | |
| 28 | + | |
| 29 | + if ([data length] < 12) { | |
| 30 | + return nil; | |
| 31 | + } | |
| 32 | + | |
| 33 | + NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding]; | |
| 34 | + if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) { | |
| 35 | + return @"image/webp"; | |
| 36 | + } | |
| 37 | + | |
| 38 | + return nil; | |
| 39 | + } | |
| 40 | + return nil; | |
| 41 | +} | |
| 42 | + | |
| 43 | +@end | ... | ... |
UIImage+MultiFormat.h
0 → 100644
| 1 | +++ a/UIImage+MultiFormat.h | |
| 1 | +// | |
| 2 | +// UIImage+MultiFormat.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/21. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <UIKit/UIKit.h> | |
| 10 | + | |
| 11 | +@interface UIImage (MultiFormat) | |
| 12 | + | |
| 13 | ++ (UIImage *)ws_imageWithData:(NSData *)data; | |
| 14 | + | |
| 15 | +@end | ... | ... |
UIImage+MultiFormat.m
0 → 100644
| 1 | +++ a/UIImage+MultiFormat.m | |
| 1 | +// | |
| 2 | +// UIImage+MultiFormat.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/21. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "UIImage+MultiFormat.h" | |
| 10 | +#import "NSData+ImageContentType.h" | |
| 11 | + | |
| 12 | +@implementation UIImage (MultiFormat) | |
| 13 | + | |
| 14 | ++ (UIImage *)ws_imageWithData:(NSData *)data | |
| 15 | +{ | |
| 16 | + if (!data) { | |
| 17 | + return nil; | |
| 18 | + } | |
| 19 | + UIImage *image; | |
| 20 | + NSString *imageContentType = [NSData ws_imageContentTypeWithData:data]; | |
| 21 | + | |
| 22 | + if ([imageContentType isEqualToString:@"image/gif"]) { | |
| 23 | + //TODO 处理GIF图片 | |
| 24 | + } | |
| 25 | + else if ([imageContentType isEqualToString:@"image/webp"]) { | |
| 26 | + //TODO 处理WEBP图片 | |
| 27 | + } | |
| 28 | + else { | |
| 29 | + image = [[UIImage alloc] initWithData:data]; | |
| 30 | + } | |
| 31 | + return image; | |
| 32 | +} | |
| 33 | + | |
| 34 | +@end | ... | ... |
UIImageView+WebCache.h
0 → 100644
| 1 | +++ a/UIImageView+WebCache.h | |
| 1 | +// | |
| 2 | +// UIImageView+WebCache.h | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/26. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import <UIKit/UIKit.h> | |
| 10 | +#import "CNLiveWebImageManager.h" | |
| 11 | + | |
| 12 | +@interface UIImageView (WebCache) | |
| 13 | + | |
| 14 | +- (void)ws_setImageWithUrl:(NSURL *)url; | |
| 15 | + | |
| 16 | +- (void)ws_setImageWithUrl:(NSURL *)url placeholderImage:(UIImage *)placeholder; | |
| 17 | + | |
| 18 | +@end | ... | ... |
UIImageView+WebCache.m
0 → 100644
| 1 | +++ a/UIImageView+WebCache.m | |
| 1 | +// | |
| 2 | +// UIImageView+WebCache.m | |
| 3 | +// WSWebImageDemo | |
| 4 | +// | |
| 5 | +// Created by 王帅 on 16/7/26. | |
| 6 | +// Copyright © 2016年 王帅. All rights reserved. | |
| 7 | +// | |
| 8 | + | |
| 9 | +#import "UIImageView+WebCache.h" | |
| 10 | +#import "CNLiveWebImageBlock.h" | |
| 11 | + | |
| 12 | +@implementation UIImageView (WebCache) | |
| 13 | + | |
| 14 | +- (void)ws_setImageWithUrl:(NSURL *)url | |
| 15 | +{ | |
| 16 | + [self ws_setImageWithUrl:url placeholderImage:nil options:0 progress:nil completed:nil]; | |
| 17 | +} | |
| 18 | + | |
| 19 | +- (void)ws_setImageWithUrl:(NSURL *)url placeholderImage:(UIImage *)placeholder | |
| 20 | +{ | |
| 21 | + [self ws_setImageWithUrl:url placeholderImage:placeholder options:0 progress:nil completed:nil]; | |
| 22 | +} | |
| 23 | + | |
| 24 | +- (void)ws_setImageWithUrl:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(CNLiveWebImageOptions)options progress:(CNLiveDownloadProgressBlock)progress completed:(CNLiveDownloadCompletedBlock)completed | |
| 25 | +{ | |
| 26 | + if (placeholder) { | |
| 27 | + self.image = placeholder; | |
| 28 | + } | |
| 29 | + | |
| 30 | + if (url) { | |
| 31 | + __weak __typeof(self) weakSelf = self; | |
| 32 | + [[CNLiveWebImageManager sharedManager] downloadWebImageWithURL:url | |
| 33 | + options:options | |
| 34 | + progress:progress | |
| 35 | + completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { | |
| 36 | + if (image && !error && finished) { | |
| 37 | + weakSelf.image = image; | |
| 38 | + } | |
| 39 | + }]; | |
| 40 | + } | |
| 41 | + else { | |
| 42 | + dispatch_async(dispatch_get_main_queue(), ^{ | |
| 43 | + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}]; | |
| 44 | + if (completed) { | |
| 45 | + completed(nil, nil, error, NO); | |
| 46 | + } | |
| 47 | + }); | |
| 48 | + } | |
| 49 | + | |
| 50 | +} | |
| 51 | + | |
| 52 | +@end | ... | ... |