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];

                                              });

                   }];



1 0
原创粉丝点击