(一二七)NSURLSession的基本用法 下載與數據獲取

簡介

NSURLSession是蘋果官方提供的一系列網絡接口庫,使用他們可以輕鬆實現下載和數據獲取等任務。在上一篇文章中,我們介紹了使用NSURLConnection下載文件和斷點續傳的功能,實現起來比較麻煩,對於文件的操作也比較繁瑣,如果使用NSURLSession,這一切都將變得極爲容易。

用法

  • 數據請求
    1.獲取URLSession單例對象,並利用該對象創建一個dataTask,使用結構體回調。
    這段代碼從網站上抓取JSON數組,解析爲OC字典。

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"http://www.soulghost.com/randompk/storeTest/baseRandom.php?type=attack"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    NSLog(@"%@",dict);
    }];

    2.開啓任務
    所有任務在創建時都是暫停的,應該手動啓動。

    [task resume];
  • 小文件下載
    1.獲取URLSession單例對象,創建一個downloadTask。

    • 注意此任務默認將文件下載到tmp文件夾,並且在下載結束後如果不處理會秒刪,一般的做法是把它移動到Document或者Caches中,當下載結束後會調用結構體,在結構體裏處理文件即可。
    • 通過NSFileManager可以實現文件的複製、移動操作,回調的location是tmp中剛剛下載的文件的URL。

      NSURLSession *session = [NSURLSession sharedSession];
      NSURLSessionDownloadTask *task = [session downloadTaskWithURL:[NSURL URLWithString:@"http://127.0.0.1/lesson1/nav.dmg"] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
      // 臨時下載到tmp,必須及時處理,否則會被系統秒刪。
      // 應該將臨時文件移動到Caches文件夾
      NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
      // 可以使用建議的文件名,與服務端一致
      NSString *file = [path stringByAppendingPathComponent:response.suggestedFilename];
      // 移動文件
      NSFileManager *mgr = [NSFileManager defaultManager];
      [mgr moveItemAtPath:location.path toPath:file error:nil];
      }];

      2.開啓任務
      所有任務在創建時都是暫停的,應該手動啓動。

      [task resume];
  • 大文件下載
    大文件常常需要獲取進度,這就需要設置代理,而不是用block回調。
    1.遵循代理方法,創建兩個成員,一個用於指向下載任務對象,另一個用於保存斷點數據。

    @interface ViewController () <NSURLSessionDownloadDelegate>
    @property (nonatomic, strong) NSURLSessionDownloadTask *task;
    @property (nonatomic, strong) NSData *resumeData;
    @end

    2.獲取URLSession單例,創建下載任務,注意使用的方法與前面不同。

    • 不要忘了保存task。
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:[NSURL URLWithString:@"http://127.0.0.1/lesson1/nav.dmg"] ];
    [task resume];
    _task = task;

    3.下載過程中會調用下面的代理方法,指示此次下載的字節數,一共下載的字節數與總字節數。

    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    NSLog(@"寫入量:%lld 下載進度:%f",bytesWritten,(double)totalBytesWritten/totalBytesExpectedToWrite);
    }

    4.下載結束後回調用下面的代理方法,從中同樣要移動文件,只是如果要想拿到響應體response的suggestedFilename,需要通過downloadTask。

    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
    NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    // 可以使用建議的文件名,與服務端一致
    NSString *file = [path stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    // 移動文件
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr moveItemAtPath:location.path toPath:file error:nil];
    
    [self.btn setTitle:@"Start" forState:UIControlStateNormal];
    }

    5.如果要暫停下載,調用下面的方法,通過回調結構體拿到斷點數據,保存在我們之前創建的成員中以便恢復。

    • 注意用weakSelf避免循環引用。
    • 任務結束後就無效了,應該讓指針指向nil來釋放內存。
    __weak typeof(self) weakSelf = self;
    [self.task cancelByProducingResumeData:^(NSData *resumeData) {
    // resumeData內部包含了下次繼續下載的開始位置
    weakSelf.resumeData = resumeData;
    weakSelf.task = nil;
    }];

    6.要恢復下載數據很容易,只需要通過斷點創建任務即可。

    • 注意清空resumeData。
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    // 傳入上次暫停下載返回的數據
    NSURLSessionDownloadTask *task = [session downloadTaskWithResumeData:self.resumeData];
    [task resume];
    _task = task;
    _resumeData = nil;
  • 斷點續傳開始時會調用下面的代理方法說明文件信息。

    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章