SDWebImage类库简介
SDWebImage 是一个十分经典的iOS获取网络图片的类库,他通过各种缓存的方式把图片保存在内存,磁盘等等的位置,并且在类库内做好的对缓存的管理,使开发者根本无需苦恼网络图片的问题,并且在最近的版本中,也开放了一些让用户可以管理cache的接口,这样使得用户操作起来更加灵活,可以满足自己app的不同需求。
SDWebImage下载图片
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
} else {
if ([challenge previousFailureCount] == 0) {
if (self.credential) {
[[challenge sender] useCredential:self.credential forAuthenticationChallenge:challenge];
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
} else {
[[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge];
}
}
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse {
responseFromCached = NO; // If this method is called, it means the response wasn't read from cache
if (self.request.cachePolicy == NSURLRequestReloadIgnoringLocalCacheData) {
// Prevents caching of responses
return nil;
}
else {
return cachedResponse;
}
}
SDWebImage图片管理
1检查URL,若是url有问题,抛出error
2先判断是否是已经失败的URL请求,若是失败请求并且选项中不包括SDWebImageRetryFailed则抛出Error
3创建operation并且把他加入队列,设置他的cacheOperation
4先检查内存,如果存在缓存,回调,如果没有检查磁盘,如果有记录内存,然后回调,如果没有返回空
5在回调中先检查是否已经被取消,取消的话在队列中删除任务,返回
6若是没有image或者选项中有SDWebImageRefreshCached,再或者代理中的返回是不能下载,去下载图片
7在上面的情况之外,若是存在image,则直接调用最外层回调,返回image,如是没有图片则调用最外层回调,传回空值,这两种情况都会在任务队列中删除任务
8下面回到流程6中说说下载图片,首先根据SDWebImageOptions设置SDWebImageDownloaderOptions,既是设置下载options
9之后开始用imageDownloader下载并且返回下载suboperation,并且设置主operation的取消block,中在队列中删除自身并且取消suboperation
10下面开始下载图片,如是任务取消,不操作,若是失败了,返回失败,并且把url加入到失败列表
11如果下载成功了,首先判断若是设置SDWebImageRefreshCached,并且返回新的image为空,则,不操作
12设下的若是需要转化图片,先利用代理转化图片
13最后保存image到cache
SDWebImage图片缓存
[self.memCache setObject:image forKey:key cost:image.size.height * image.size.width * image.scale];
NSString *filePath = [self.diskCachePath stringByAppendingPathComponent:fileName];
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil];
size += [attrs fileSize]; //获取文件大小
NSDirectoryEnumerator *fileEnumerator = [_fileManager enumeratorAtPath:self.diskCachePath];
count = [[fileEnumerator allObjects] count]; //获取目录下所有文件
杂七杂八的知识点
1.如何根据一个图片的NSData判断图片的类型呢,我们往往不能单纯的根据文件的后缀就判断文件的类型,而应该根据不同格式的头来判定图片的类型,SD是在NSData+
ImageContentType中对头进行了初步的判断得到相应的MIME,细节可以看这里 http://blog.csdn.net/include1224/article/details/5195470
2.运行时,在SD中使用了一些运行时的方法,比如把某个类的一些数据绑定到运行时中,用的时候在去用某个key取出来使用,大家可以去详细的了解下运行时的东西,非常有用
- (NSMutableDictionary *)imageURLStorage {
NSMutableDictionary *storage = objc_getAssociatedObject(self, &imageURLStorageKey);
if (!storage)
{
storage = [NSMutableDictionary dictionary];
objc_setAssociatedObject(self, &imageURLStorageKey, storage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return storage;
}
SDWebimage 的任务控制也是使用这个做个 每个控件都动态绑定一个字典,根据不同的任务(key)向字典里面存储任务,每次有新任务可以取出operation然后取消。
3针对图片的处理,使用的是ImageI/O框架的内容,通过获取image的信息来显示GIF等,这里看细节 https://developer.apple.com/library/ios/documentation/graphicsimaging/conceptual/ImageIOGuide/ImageIOGuide.pdf
在这里 SD 使用了 CGImageSourceRef 来显示GIF并且 根据图片信息进行方向纠错
4在operation中使用runloop阻塞线程,这是为了线程安全,关于iOS线程的知识参见下面的两个连接
http://www.dreamingwish.com/article/ios-multi-threaded-programming-a-multi-threaded-programming.html
http://www.cocoachina.com/bbs/simple/?t43852.html