美文网首页AFNetworking源码探究
AFNetworking源码探究(八) —— AFURLSess

AFNetworking源码探究(八) —— AFURLSess

作者: 刀客传奇 | 来源:发表于2018-03-01 10:14 被阅读37次

    版本记录

    版本号 时间
    V1.0 2018.03.01

    前言

    我们做APP发起网络请求,都离不开一个非常有用的框架AFNetworking,可以说这个框架的知名度已经超过了苹果的底层网络请求部分,很多人可能不知道苹果底层是如何发起网络请求的,但是一定知道AFNetworking,接下来几篇我们就一起详细的解析一下这个框架。感兴趣的可以看上面写的几篇。
    1. AFNetworking源码探究(一) —— 基本介绍
    2. AFNetworking源码探究(二) —— GET请求实现之NSURLSessionDataTask实例化(一)
    3. AFNetworking源码探究(三) —— GET请求实现之任务进度设置和通知监听(一)
    4. AFNetworking源码探究(四) —— GET请求实现之代理转发思想(一)
    5. AFNetworking源码探究(五) —— AFURLSessionManager中NSURLSessionDelegate详细解析(一)
    6. AFNetworking源码探究(六) —— AFURLSessionManager中NSURLSessionTaskDelegate详细解析(一)
    7. AFNetworking源码探究(七) —— AFURLSessionManager中NSURLSessionDataDelegate详细解析(一)

    回顾

    主要介绍了NSURLSessionDataDelegate中四个代理方法的实现及其使用场景和注意事项。这一篇我们就看一下NSURLSessionDownloadDelegate这个代理。


    1. - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location;

    首先看一下苹果原生的API接口

    /* Sent when a download task that has completed a download.  The delegate should 
     * copy or move the file at the given location to a new location as it will be 
     * removed when the delegate message returns. URLSession:task:didCompleteWithError: will
     * still be called.
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                  didFinishDownloadingToURL:(NSURL *)location;
    

    看一下AFN中该方法的实现

    - (void)URLSession:(NSURLSession *)session
          downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didFinishDownloadingToURL:(NSURL *)location
    {
        AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
        if (self.downloadTaskDidFinishDownloading) {
            NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
            if (fileURL) {
                delegate.downloadFileURL = fileURL;
                NSError *error = nil;
                [[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error];
                if (error) {
                    [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
                }
    
                return;
            }
        }
    
        if (delegate) {
            [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
        }
    }
    

    这里代码都很简单,就不多说了,这里也做了代理的转发。

    if (delegate) {
        [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
    }
    

    还记得那两个参与转发的代理吗?

    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)error;
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
    

    2. - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

    首先看一下苹果原生的API接口

    /* Sent periodically to notify the delegate of download progress. */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                               didWriteData:(int64_t)bytesWritten
                                          totalBytesWritten:(int64_t)totalBytesWritten
                                  totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
    

    看一下AFN中该方法的实现

    - (void)URLSession:(NSURLSession *)session
          downloadTask:(NSURLSessionDownloadTask *)downloadTask
          didWriteData:(int64_t)bytesWritten
     totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
        if (self.downloadTaskDidWriteData) {
            self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
        }
    }
    

    这个方法和参数都很好理解,我就说一点,totalBytesExpectedToWrite这个参数表示期望收到的文件总字节数,是由Content-Length header提供。如果没有提供,默认是NSURLSessionTransferSizeUnknown


    3. - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes;

    首先看一下苹果原生的API接口

    /* Sent when a download has been resumed. If a download failed with an
     * error, the -userInfo dictionary of the error will contain an
     * NSURLSessionDownloadTaskResumeData key, whose value is the resume
     * data. 
     */
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                          didResumeAtOffset:(int64_t)fileOffset
                                         expectedTotalBytes:(int64_t)expectedTotalBytes;
    

    看一下AFN中该方法的实现

    - (void)URLSession:(NSURLSession *)session
          downloadTask:(NSURLSessionDownloadTask *)downloadTask
     didResumeAtOffset:(int64_t)fileOffset
    expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        if (self.downloadTaskDidResume) {
            self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
        }
    }
    
    • 当下载被取消或者失败后重新恢复下载时调用。
    • 如果一个正在下载任务被取消或者失败了,你可以请求一个resumeData对象(比如在userInfo字典中通过NSURLSessionDownloadTaskResumeData这个键来获取到resumeData)并使用它来提供足够的信息以重新开始下载任务。
      随后,你可以使用resumeData作为downloadTaskWithResumeData:downloadTaskWithResumeData:completionHandler:的参数。当你调用这些方法时,你将开始一个新的下载任务。一旦你继续下载任务,session会调用它的代理方法URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:其中的downloadTask参数表示的就是新的下载任务,这也意味着下载重新开始了。
    • 注意:fileOffset这个参数,如果文件缓存策略或者最后文件更新日期阻止重用已经存在的文件内容,那么该值为0。否则,该值表示当前已经下载data的偏移量。
    • 前面几篇讲解的那么多代理方法中,我们做的处理都是相对于这个sessionManager所有的request的。是公用的处理。而转发的3个代理方法到AF的自定义deleagate,作用是需要对应每个task去私有化处理。

    后记

    本篇主要讲述的就是NSURLSessionDownloadDelegate代理在AFN中实现的几个方法。喜欢的给个关注吧~~~

    相关文章

      网友评论

        本文标题:AFNetworking源码探究(八) —— AFURLSess

        本文链接:https://www.haomeiwen.com/subject/zjzwxftx.html