ios学习----------SDWebImage框架解析(3)
来源:互联网 发布:知乎机构账号 编辑:程序博客网 时间:2024/04/29 11:33
3、创建异步下载器,下载图片
- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock {
封装了异步下载操作
__block SDWebImageDownloaderOperation *operation;
__weak __typeof(self)wself =self;
[selfaddProgressCallback:progressBlock completedBlock:completedBlockforURL:url createCallback:^{
下载超时时间是15秒
NSTimeInterval timeoutInterval = wself.downloadTimeout;
if (timeoutInterval == 0.0) {
timeoutInterval =15.0;
}
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
创建下载的请求request
NSMutableURLRequest *request = [[NSMutableURLRequestalloc] initWithURL:urlcachePolicy:(options & SDWebImageDownloaderUseNSURLCache ?NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData)timeoutInterval:timeoutInterval];
request的HTTPShouldHandleCookies是否给request设置cookies随request发送出去
request.HTTPShouldHandleCookies = (options &SDWebImageDownloaderHandleCookies);
request.HTTPShouldUsePipelining =YES;
if (wself.headersFilter) {
request.allHTTPHeaderFields = wself.headersFilter(url, [wself.HTTPHeaderscopy]);
}
else {
request.allHTTPHeaderFields = wself.HTTPHeaders;
}
operation = [[wself.operationClassalloc] initWithRequest:request
options:options
progress:^(NSInteger receivedSize,NSInteger expectedSize) {
SDWebImageDownloader *sself = wself;
if (!sself) return;
__block NSArray *callbacksForURL;
dispatch_sync(sself.barrierQueue, ^{
callbacksForURL = [sself.URLCallbacks[url]copy];
});
for (NSDictionary *callbacksin callbacksForURL) {
dispatch_async(dispatch_get_main_queue(), ^{
SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey];
if (callback) callback(receivedSize, expectedSize);
});
}
}
completed:^(UIImage *image,NSData *data, NSError *error,BOOL finished) {
SDWebImageDownloader *sself = wself;
if (!sself) return;
__block NSArray *callbacksForURL;
dispatch_barrier_sync(sself.barrierQueue, ^{
callbacksForURL = [sself.URLCallbacks[url]copy];
if (finished) {
[sself.URLCallbacksremoveObjectForKey:url];
}
});
for (NSDictionary *callbacksin callbacksForURL) {
SDWebImageDownloaderCompletedBlock callback = callbacks[kCompletedCallbackKey];
if (callback) callback(image, data, error, finished);
}
}
cancelled:^{
SDWebImageDownloader *sself = wself;
if (!sself) return;
dispatch_barrier_async(sself.barrierQueue, ^{
[sself.URLCallbacksremoveObjectForKey:url];
});
}];
这个简单,就是说要不要解压缩图片。解压缩已经下载的图片或者在缓存中的图片,可以提高性能,但是会耗费很多空间,缺省情况下是要解压缩图片。
operation.shouldDecompressImages = wself.shouldDecompressImages;
web 服务可以在返回 http 响应时附带认证要求的challenge,作用是询问 http 请求的发起方是谁,这时发起方应提供正确的用户名和密码(即认证信息),然后 web 服务才会返回真正的 http 响应。收到认证要求时,NSURLConnection 的委托对象会收到相应的消息并得到一个 NSURLAuthenticationChallenge 实例。该实例的发送方遵守 NSURLAuthenticationChallengeSender 协议。为了继续收到真实的数据,要向该发送方向发回一个 NSURLCredential 实例。
if (wself.urlCredential) {
operation.credential = wself.urlCredential;
}else if (wself.username && wself.password) {
operation.credential = [NSURLCredentialcredentialWithUser:wself.usernamepassword:wself.passwordpersistence:NSURLCredentialPersistenceForSession];
}
设置operation的优先级
if (options &SDWebImageDownloaderHighPriority) {
operation.queuePriority =NSOperationQueuePriorityHigh;
} elseif (options &SDWebImageDownloaderLowPriority) {
operation.queuePriority =NSOperationQueuePriorityLow;
}
将operation添加到队列中,如果是lifo栈模式,需要设置依赖关系
[wself.downloadQueueaddOperation:operation];
if (wself.executionOrder ==SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[wself.lastAddedOperationaddDependency:operation];
wself.lastAddedOperation = operation;
}
}];
return operation;
}
**********************
- (void)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageNoParamsBlock)createCallback {
// The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data.
url作为字典中的key不能为空
if (url == nil) {
if (completedBlock != nil) {
completedBlock(nil,nil, nil, NO);
}
return;
}
dispatch_barrier_sync同步执行,等待队列self.barrierQueue中的任务执行完毕后,执行block内容
dispatch_barrier_sync(self.barrierQueue, ^{
BOOL first = NO;
字典self.URLCallbacks没有该key,则创建说明该url是第一次进行下载
if (!self.URLCallbacks[url]) {
self.URLCallbacks[url] = [NSMutableArraynew];
first =YES;
}
// Handle single download of simultaneous download request for the same URL
NSMutableArray *callbacksForURL = self.URLCallbacks[url];
NSMutableDictionary *callbacks = [NSMutableDictionarynew];
存储了对应的progressBlock和completedBlock
if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlockcopy];
if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlockcopy];
[callbacksForURLaddObject:callbacks];
self.URLCallbacks[url] = callbacksForURL;
if (first) {
createCallback();
}
});
}
**********************
三个block的解析
progress:^(NSInteger receivedSize, NSIntegerexpectedSize) {
SDWebImageDownloader *sself = wself;
if (!sself) return;
__block NSArray *callbacksForURL;
dispatch_sync(sself.barrierQueue, ^{
callbacksForURL =[sself.URLCallbacks[url] copy];
});
放在主线程中进行 反复调用返回下载结果
for (NSDictionary *callbacks in callbacksForURL) {
dispatch_async(dispatch_get_main_queue(), ^{
SDWebImageDownloaderProgressBlock callback= callbacks[kProgressCallbackKey];
if (callback) callback(receivedSize,expectedSize);
});
}
}
核心代码:同步函数
dispatch_sync(sself.barrierQueue, ^{ [sself.URLCallbacks[url] copy];
});
completed:^(UIImage *image, NSData *data, NSError*error, BOOL finished) {
SDWebImageDownloader *sself = wself;
if (!sself) return;
__block NSArray *callbacksForURL;
队列sself.barrierQueue任务执行完毕执行block
dispatch_barrier_sync(sself.barrierQueue, ^{
获取下载数组中的block
callbacksForURL=[sself.URLCallbacks[url] copy];
if (finished) {
[sself.URLCallbacksremoveObjectForKey:url];
}
});
下载完成后调用bllock
for (NSDictionary *callbacks in callbacksForURL) {
SDWebImageDownloaderCompletedBlock callback=callbacks[kCompletedCallbackKey];
if (callback) callback(image, data, error, finished);
}
}
cancelled:^{
SDWebImageDownloader *sself = wself;
if (!sself) return;
dispatch_barrier_async(sself.barrierQueue, ^{
[sself.URLCallbacks removeObjectForKey:url];
});
}];
- iOS客户端学习-SDWebImage
- ios学习----------SDWebImage框架解析(3)
- iOS 第三方框架-SDWebImage解读
- iOS图片加载框架-SDWebImage
- iOS图片加载框架-SDWebImage
- iOS学习----------SDWebImage框架解析(1)
- iOS学习----------SDWebImage框架解析(2)
- iOS图片加载-SDWebImage
- iOS----------SDWebimage源码解析(3)
- iOS----------SDWebimage源码解析(1)
- iOS----------SDWebimage源码解析(2)
- iOS----------SDWebimage源码解析(4)
- iOS----------SDWebimage源码解析(5)
- SDWebImage源码剖析(-)
- IOS 网络-深入浅出(一 )-> 三方SDWebImage
- iOS开发-SDWebImage的回调不addSubView不会调用
- IOS 网络浅析-(六 网络图片获取之三方SDWebImage-master)
- iOS 10 适配系列-UserNotifications 框架解析
- Maven简明教程(1)---下载与安装
- unar万能linux解压工具
- xcode svn scheduled for addition, but is missing
- 异常NoSuchMethodError: android.app.Notification$Builder.build解决方案
- 新版本OpenGL (>3.3.0) 学习
- ios学习----------SDWebImage框架解析(3)
- encode()和decode()
- 10 things you didn't know you can do with Unreal Engine 4
- Learn Python in Y Minutes(有时间再慢慢翻译)
- 《孙鑫vc++视频20集》【最后更新日期:16/04/20
- ios app 开发中ipa重新签名步骤介绍
- UIBezierPath和CABasicAnimation画一条从左至右有动画的线,画曲线
- Android中Handler的用法
- php5.5+apache2.4安装 环境搭建