在iOS 7以前使用的網絡服務是經過使用NSURLConnection中的全局狀態來管理Cookie和身份驗證,所以可能致使兩個不一樣的連接同時使用這個設置時產生衝突。在iOS7的NSURLSession 中蘋果公司決定改掉這個被人詬病的毛病。緩存
在這裏咱們將使用NSURLSession來王成三種不一樣的下載方案。下面的文章咱們將實現:安全
Simple dowload
服務器
若是咱們要利用NSURLSession進行數據傳輸咱們須要作以下的步驟
cookie
1.建立一個NSURLSessionConfiguration網絡
2.建立NSSession並經過第一步建立好的NSURLSessionConfiguration來設置工做模式和網絡設置session
工做模式分爲:app
默認模式(default):工做模式相似魚原來的NSURLConnection,可使用緩存的Cache,cookie 等異步
實時模式(ephemeral):不是用緩存的Cache,Cookie和受權async
後臺模式 (background):在後臺完成上傳和下載,建立Configuration對象的時候須要給NSString一個ID用於追蹤完成工做的Session是那一個。url
對於簡單的下載咱們將只使用默認的會話:
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
一旦一個配置對象被建立那麼它的屬性就能夠控制它的動做。例如,它能夠設置接收TLS安全級別,無論cookies是否容許和是否超時。這裏兩個比較有趣的特性是allowsCellularAccess和discretionary。前者指定的設備是否被容許運行的網絡session,只有一個蜂窩數據可用。設置一個會話做爲全權使操做系統來安排網絡訪問明智的時間 - 也就是當一個無線網絡可用,而當該設備具備良好的動力性。這主要是利用background session,所以默認爲true的background session。
一旦咱們有一個會話配置對象,咱們能夠建立會話自己。
NSURLSession *inProcessSession;
inProcessSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
注意這裏咱們也設置本身做爲本身的一個委託。委託方法用來通知咱們的數據傳輸的進度和當挑戰驗證請求信息 咱們將很快實施一些適當的方法。
數據傳輸封裝在任務 - 其中有三種類型:
NSURLSessionUploadTask:上傳用的Task,傳完以後不會再下載返回結果;
NSURLSessionDownloadTask:下載用的Task;
NSURLSessionDataTask:能夠上傳內容,上傳完成以後再進行下載。
爲了在會話中進行傳輸,咱們須要建立一個任務。對於一個簡單的文件下載:
NSString *url = @"hettp://appropriate/url/here";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLSessionDownloadTask *cancellabelTask = [inProcessSession downloadTaskWithRequest:request];
[cancellableTask resume];
這一切就這麼簡單 - 如今會話將異步嘗試下載該文件在指定的URL。
爲了弄個所需的文件下載,咱們須要實現一個委託方法:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
//咱們已經成功的完成下載,如今要保存文件
NSFileManage *fileManager = [NSFileManager defauleManager];
NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDoma\inMask];
NSURL *dcoumentsDirectory = URLs[0];
NSURL *destinationPath = [documentsDirectory URLByAppendingPathCOmponent:[location lastPathComponent]];
NSError *error;
//確保咱們已經覆蓋了已經存在的
[fileManager removeItemAtURL:destinationPath error:NULL];
BOOL success = [fileManager copyItemAtURL:location toURL:destinationPath error:&error];
if (success)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithContentOfFile:[destinationPath path]];
self.imageView.image = image;
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.hidden = NO;
});
} else
{
NSLog(@"Couldn't copy the dowloaded file");
}
if (downloadTask == cancelableTask){
cancellableTask = nil;
}
}
這種方法是在NSURLSessionDownloadTaskDelegate定義。咱們得到經過下載的文件的臨時位置,因此在這段代碼中咱們保存它關閉的文件目錄,而後(由於咱們有一個圖片)顯示給用戶。
上述委託方法只被調用,若是下載任務成功完成。下面的方法是NSURLSessionDelegate和被調用每個任務完成後,不論它是否成功完成。
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task dedCompleteWithError:(NSError *)error
{
dispatch_async(dispatch_get_mian_queue(),^{self.progressInicator.hiddent = YES;})
}
若是錯誤對象爲零則任務完成沒有問題。不然,有可能對其進行查詢,找出問題是什麼。若是部分下載已完成,則錯誤對象包含對一個NSData對象,它能夠用來恢復傳輸在稍後的階段。
跟蹤進度
你會注意到,咱們在最後一節的末尾藏進度指示任務完成方法的一部分。此更新進度條的進度再簡單不過了。還有就是這是在任務的生命週期被稱爲零次或屢次額外的委託方法:
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int62_t)bytesWritten BytesWritten:(int64_t)totalBytesWritten totalByteExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite;
dispatch_async(dispatch_get_main_queue() ^{self.progressIndicator.hidden = NO; self.progressIndicator.progress = currentProgress;})
}
這是另外一種方法,它是NSURLSessionDownloadTaskDelegate的一部分,咱們在這裏使用它來
估計進度和更新進度指示器。
退出下載
即便NSURLConnection被取消也不會消失。這是一個簡單的能力,與取消NSURLSessionTask不一樣。
-(IBAction)cancelCancellabel:(id)sender{
if (cancellableTask){
[cancellabelTask cancel];
cancellableTask = nil;
}
}
就是這麼簡單!值得一提的是UIRLSession:task:didCompleteWithError:delegate方法將被在調用一次後取消,通常你可以適當的更新UI。這極可能取消任務URLSession:downloadTask:didWriteData:BytesWritten:totalBytesExpectedToWrite:方法,可能會被調用,可是didComplete方法可定時最後的。
斷點續傳下載
它也能夠很容易地恢復下載。還存在另外一種取消方法,該方法提供了一個NSData對象能夠用來建立一個新的任務繼續傳輸在稍後的階段。若是服務器支持續傳而後將數據對象將包括已經下載的內容。
- (IBAction)cancelCancellabel:(id)sender{
if(self.resumableTask){
[self.resumableTask cancelByProducingResumeData:^(NSData *resumeData) { partialDownload = resumeData; self.resumableTask = nil;}];
}
}
在這裏,咱們已經把恢復數據到ivar,咱們之後能夠用它來恢復下載。
在建立下載任務,而不是提供你能提供一個恢復數據對象的請求:
if (!self.resumableTask){
if(partialDownload){
self.resumableTask = [inProcessSession downloadTaskWithResumeData:partialDownload];
}else{
NSString *url = @"dizhi";
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
self.resumableTask = [inProcessSession downloadTaskWithResques:request];
}
[self.resumableTask resume];
}
若是咱們已經有一個paritialDownload對象,而後建立一個task來使用這個對象,不然咱們將像之前同樣建立task。惟一一件須要記住的事情就是當process結束咱們須要設置 partialDownload = nil;
不想寫了,你徹底能夠參考上面的步驟來完成你的後臺下載!