NSURLSession的了解

在蘋(píng)果徹底棄用NSURLConnection之后自己總結(jié)的一個(gè)網(wǎng)上的內(nèi)容,加上自己寫(xiě)的小Demo所刀,很多都是借鑒網(wǎng)絡(luò)上的資源仰泻,有需要的朋友可以看看。
排版之前也是亂弄的(因?yàn)橹熬妥约嚎疵磭澹?br> 可以看Demo下的pdf
Demo地址:https://github.com/Fuhanyu/FHYNSURLSessionDemo

一.引言:

由于Xcode 7中篮愉,NSURLConnection的API已經(jīng)正式被蘋(píng)果棄用腐芍。雖然該API將繼續(xù)運(yùn)行,但將沒(méi)有新功能將被添加试躏,并且蘋(píng)果已經(jīng)通知所有基于網(wǎng)絡(luò)的功能猪勇,以充分使NSURLSession向前發(fā)展。

二.快速了解與改變AFNetworking篇:

AFNetworking是一款在OS X和iOS下都令人喜愛(ài)的網(wǎng)絡(luò)庫(kù),為了迎合iOS新版本的升級(jí), AFNetworking在3.0版本中刪除了基于 NSURLConnection API的所有支持颠蕴。如果你的項(xiàng)目以前使用過(guò)這些API泣刹,建議您立即升級(jí)到基于 NSURLSession 的API的AFNetworking的版本。

AFNetworking 1.0建立在NSURLConnection的基礎(chǔ)API之上 犀被,AFNetworking 2.0開(kāi)始使用NSURLConnection的基礎(chǔ)API 椅您,以及較新基于NSURLSession的API的選項(xiàng)寡键。 AFNetworking 3.0現(xiàn)已完全基于NSURLSession的API,這降低了維護(hù)的負(fù)擔(dān)开伏,同時(shí)支持蘋(píng)果增強(qiáng)關(guān)于NSURLSession提供的任何額外功能遭商。

1.棄用的類

下面的類已從AFNetworking 3.0中廢棄:

  • AFURLConnectionOperation
  • AFHTTPRequestOperation
  • AFHTTPRequestOperationManager

2.讓我們看一下原來(lái)封裝的簡(jiǎn)單網(wǎng)絡(luò)處理類

//創(chuàng)建一個(gè)HTTP請(qǐng)求操作管理對(duì)象
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
//通過(guò)設(shè)置responseSerializer,自動(dòng)完成返回?cái)?shù)據(jù)的解析劫流,直接獲取json格式的responseObject巫玻。
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json", @"text/plain", @"text/html", nil];

//允許無(wú)效的 SSL 證書(shū):
//NSURLConnection已經(jīng)封裝了https連接的建立丛忆、數(shù)據(jù)的加密解密功能,我們直接使用NSURLConnection是可以訪問(wèn)https網(wǎng)站的仍秤,但NSURLConnection并沒(méi)有驗(yàn)證證書(shū)是否合法熄诡,無(wú)法避免中間人攻擊。要做到真正安全通訊诗力,需要我們手動(dòng)去驗(yàn)證服務(wù)端返回的證書(shū)凰浮,AFSecurityPolicy封裝了證書(shū)驗(yàn)證的過(guò)程,讓用戶可以輕易使用苇本,除了去系統(tǒng)信任CA機(jī)構(gòu)列表驗(yàn)證袜茧,還支持SSL Pinning方式的驗(yàn)證。
manager.securityPolicy.allowInvalidCertificates = YES;//生產(chǎn)環(huán)境不建議使用

[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"%@",responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];

3.AFHTTPRequestOperationManager 核心代碼

如果你以前使用 AFHTTPRequestOperationManager 瓣窄, 你將需要遷移去使用AFHTTPSessionManager笛厦。 以下的類在兩者過(guò)渡間并沒(méi)有變化:

  • securityPolicy 安全政策
  • requestSerializer 請(qǐng)求串行器
  • responseSerializer 響應(yīng)串行器

AFNetworking 2.x

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"請(qǐng)求的url" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"成功");
} failure:^(AFHTTPRequestOperation operation, NSErrorerror) {
NSLog(@"失敗");
}];

AFNetworking 3.0
AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
[session GET:@"請(qǐng)求的url" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"成功");
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"失敗");
}];

三.基本了解NSURLSession

  • 1.了解Apple 的網(wǎng)絡(luò)連接API

  • NSURLConnection 作為 Core Foundation / CFNetwork 框架的 API 之上的一個(gè)抽象,在 2003 年俺夕,隨著第一版的 Safari 的發(fā)布就發(fā)布了裳凸。NSURLConnection 這個(gè)名字,實(shí)際上是指代的 Foundation 框架的 URL 加載系統(tǒng)中一系列有關(guān)聯(lián)的組件:NSURLRequest劝贸、NSURLResponse姨谷、NSURLProtocol、 NSURLCache悬荣、NSHTTPCookieStorage菠秒、NSURLCredentialStorage 以及同名類 NSURLConnection疙剑。

  • NSURLRequest 被傳遞給 NSURLConnection。被委托對(duì)象(遵守以前的非正式協(xié)議 <NSURLConnectionDelegate> 和<NSURLConnectionDataDelegate>)異步地返回一個(gè) NSURLResponse 以及包含服務(wù)器返回信息的 NSData嚼蚀。

  • NSURLConnection 作為網(wǎng)絡(luò)基礎(chǔ)架構(gòu),已經(jīng)服務(wù)了成千上萬(wàn)的 iOS 和 Mac OS 程序导帝,并且做的還算相當(dāng)不錯(cuò)。但是這些年虐秦,一些用例——尤其是在 iPhone 和 iPad 上面——已經(jīng)對(duì) NSURLConnection 的幾個(gè)核心概念提出了挑戰(zhàn)蜈彼,讓蘋(píng)果有理由對(duì)它進(jìn)行重構(gòu)幸逆。

  • 在 2013 的 WWDC 上,蘋(píng)果推出了 NSURLConnection 的繼任者:NSURLSession蚕甥。

  • 和 NSURLConnection 一樣,NSURLSession 指的也不僅是同名類 NSURLSession爱沟,還包括一系列相互關(guān)聯(lián)的類。NSURLSession 包括了與之前相同的組件括享,NSURLRequest 與 NSURLCache铃辖,但是把 NSURLConnection 替換成了NSURLSession、NSURLSessionConfiguration 以及 NSURLSessionTask 的 3 個(gè)子類:NSURLSessionDataTask犬第,NSURLSessionUploadTask,NSURLSessionDownloadTask遥椿。

  • 與 NSURLConnection 相比家浇,NSURLsession 最直接的改進(jìn)就是可以配置每個(gè) session 的緩存,協(xié)議莺琳,cookie惭等,以及證書(shū)策略(credential policy),甚至跨程序共享這些信息秤茅。這將允許程序和網(wǎng)絡(luò)基礎(chǔ)框架之間相互獨(dú)立框喳,不會(huì)發(fā)生干擾。每個(gè)NSURLSession 對(duì)象都由一個(gè) NSURLSessionConfiguration 對(duì)象來(lái)進(jìn)行初始化拼余,后者指定了剛才提到的那些策略以及一些用來(lái)增強(qiáng)移動(dòng)設(shè)備上性能的新選項(xiàng)凡橱。

  • NSURLSession 中另一大塊就是 session task稼钩。它負(fù)責(zé)處理數(shù)據(jù)的加載以及文件和數(shù)據(jù)在客戶端與服務(wù)端之間的上傳和下載静秆。NSURLSessionTask 與 NSURLConnection 最大的相似之處在于它也負(fù)責(zé)數(shù)據(jù)的加載扶认,最大的不同之處在于所有的 task 共享其創(chuàng)造者 NSURLSession 這一公共委托者(common delegate)辐宾。

NSURLSessionTask

NSURLsessionTask 是一個(gè)抽象類,其下有 3 個(gè)實(shí)體子類可以直接使用:NSURLSessionDataTask誉察、NSURLSessionUploadTask、NSURLSessionDownloadTask综液。這 3 個(gè)子類封裝了現(xiàn)代程序三個(gè)最基本的網(wǎng)絡(luò)任務(wù):獲取數(shù)據(jù)谬莹,比如 JSON 或者 XML,上傳文件和下載文件蕉扮。

當(dāng)一個(gè) NSURLSessionDataTask 完成時(shí),它會(huì)帶有相關(guān)聯(lián)的數(shù)據(jù)奔则,而一個(gè) NSURLSessionDownloadTask 任務(wù)結(jié)束時(shí),它會(huì)帶回已下載文件的一個(gè)臨時(shí)的文件路徑抽莱。因?yàn)橐话銇?lái)說(shuō)匕垫,服務(wù)端對(duì)于一個(gè)上傳任務(wù)的響應(yīng)也會(huì)有相關(guān)數(shù)據(jù)返回年缎,所以NSURLSessionUploadTask 繼承自 NSURLSessionDataTask。

所有的 task 都是可以取消犁柜,暫桶峭螅或者恢復(fù)的。當(dāng)一個(gè) download task 取消時(shí)蹋盆,可以通過(guò)選項(xiàng)來(lái)創(chuàng)建一個(gè)恢復(fù)數(shù)據(jù)(resume data),然后可以傳遞給下一次新創(chuàng)建的 download task析藕,以便繼續(xù)之前的下載。

1??NSURLSessionDataTask

2.GET請(qǐng)求

//1.創(chuàng)建NSURLSession對(duì)象(可以獲取單例對(duì)象)
NSURLSession *session = [NSURLSession sharedSession];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://api.liwushuo.com/v2/banners?channel=iOS"]];
//2.根據(jù)NSURLSession對(duì)象創(chuàng)建一個(gè)Task
/*
 注意:該block是在子線程中調(diào)用的,如果拿到數(shù)據(jù)之后要做一些UI刷新操作,那么需要回到主線程刷新
 第一個(gè)參數(shù):需要發(fā)送的請(qǐng)求對(duì)象
 block:當(dāng)請(qǐng)求結(jié)束拿到服務(wù)器響應(yīng)的數(shù)據(jù)時(shí)調(diào)用block
 block-NSData:該請(qǐng)求的響應(yīng)體
 block-NSURLResponse:存放本次請(qǐng)求的響應(yīng)信息仑鸥,響應(yīng)頭意狠,真實(shí)類型為NSHTTPURLResponse
 block-NSErroe:請(qǐng)求錯(cuò)誤信息
 */
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    //拿到響應(yīng)頭信息
    NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //4.解析拿到的響應(yīng)數(shù)據(jù)
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@ \n %@", dic, res.allHeaderFields);
}];
//3.執(zhí)行Task
//注意:剛創(chuàng)建出來(lái)的task默認(rèn)是掛起狀態(tài)的澎灸,需要調(diào)用該方法來(lái)啟動(dòng)任務(wù)(執(zhí)行任務(wù)
[dataTask resume];

3.第二種GET請(qǐng)求

//1.創(chuàng)建NSURLSession對(duì)象(可以獲取單例對(duì)象)
NSURLSession session = [NSURLSession sharedSession];
//2.創(chuàng)建一個(gè)Task
//注意:該方法內(nèi)部默認(rèn)會(huì)把URL對(duì)象包裝成一個(gè)NSURLRequest對(duì)象(默認(rèn)是GET請(qǐng)求)
//方法參數(shù)說(shuō)明
/

//第一個(gè)參數(shù):發(fā)送請(qǐng)求的URL地址
//block:當(dāng)請(qǐng)求結(jié)束拿到服務(wù)器響應(yīng)的數(shù)據(jù)時(shí)調(diào)用block
//block-NSData:該請(qǐng)求的響應(yīng)體
//block-NSURLResponse:存放本次請(qǐng)求的響應(yīng)信息拦止,響應(yīng)頭其兴,真實(shí)類型為NSHTTPURLResponse
//block-NSErroe:請(qǐng)求錯(cuò)誤信息
*/
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://api.liwushuo.com/v2/banners?channel=iOS"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//拿到響應(yīng)頭信息
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //4.解析拿到的響應(yīng)數(shù)據(jù)
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
    NSLog(@"%@ \n %@", dic, res.allHeaderFields);
}];

[dataTask resume];

4.POST請(qǐng)求

 //1.創(chuàng)建NSURLSession對(duì)象(可以獲取單例對(duì)象)
NSURLSession *session = [NSURLSession sharedSession];

//2.根據(jù)NSURLSession對(duì)象創(chuàng)建一個(gè)Task

NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];

//創(chuàng)建一個(gè)請(qǐng)求對(duì)象顶瞒,并這是請(qǐng)求方法為POST,把參數(shù)放在請(qǐng)求體中傳遞
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];

NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
    //拿到響應(yīng)頭信息
    NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;

    //解析拿到的響應(yīng)數(shù)據(jù)
    NSLog(@"%@\n%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],res.allHeaderFields);
}];

//3.執(zhí)行Task
//注意:剛創(chuàng)建出來(lái)的task默認(rèn)是掛起狀態(tài)的元旬,需要調(diào)用該方法來(lái)啟動(dòng)任務(wù)(執(zhí)行任務(wù))
[dataTask resume];

2??NSURLSessionDownloadTask

1.使用NSURLSession和NSURLSessionDownload可以很方便的實(shí)現(xiàn)文件下載操作

//
// NSURLSessionNetWork.m
// FHYNetworkHandle
//
// Created by 付寒宇 on 15/11/7.
// Copyright ? 2015年 付寒宇. All rights reserved.
//

import "NSURLSessionDownloadTaskShow.h"

@interface NSURLSessionDownloadTaskShow ()<NSURLSessionDownloadDelegate>
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@property (strong, nonatomic) IBOutlet UIProgressView *progressBar;
@property (strong, nonatomic) IBOutlet UIButton *start;
@property (strong, nonatomic) IBOutlet UIButton *pause;
@property (strong, nonatomic) IBOutlet UIButton *resume;
@property (atomic, strong) NSURLSessionDownloadTask *task;
@property (atomic, strong) NSData *partialData;

@end

@implementation NSURLSessionDownloadTaskShow

  • (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"NSURLSessionDownloadTask";
    }

//創(chuàng)建Session對(duì)象

  • (NSURLSession *)createASession{
    //創(chuàng)建NSURLSession配置對(duì)象Configuration
    NSURLSessionConfiguration configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    //創(chuàng)建NSURLSession,并設(shè)置代理
    /

    第一個(gè)參數(shù):session對(duì)象的全局配置設(shè)置榴徐,一般使用默認(rèn)配置就可以
    第二個(gè)參數(shù):誰(shuí)成為session對(duì)象的代理
    第三個(gè)參數(shù):代理方法在哪個(gè)隊(duì)列中執(zhí)行(在哪個(gè)線程中調(diào)用),如果是主隊(duì)列那么在主線程中執(zhí)行,如果是非主隊(duì)列法绵,那么在子線程中執(zhí)行
    */
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    return session;
    }
    //創(chuàng)建Session請(qǐng)求

  • (NSURLRequest *)createARequest{
    //注意:如果要發(fā)送POST請(qǐng)求箕速,那么請(qǐng)?jiān)O(shè)置一些請(qǐng)求頭信息
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"]];
    return request;
    }
    //開(kāi)始下載

  • (IBAction)start:(id)sender {
    //用NSURLSession和NSURLRequest創(chuàng)建網(wǎng)絡(luò)任務(wù)

    self.task = [[self createASession] downloadTaskWithRequest:[self createARequest]];
    [self.task resume];
    }
    //暫停下載

  • (IBAction)pause:(id)sender {
    NSLog(@"Pause download task");
    if (self.task) {
    //取消下載任務(wù),把已下載數(shù)據(jù)存起來(lái)
    //如果采取這種方式來(lái)取消任務(wù),那么該方法會(huì)通過(guò)resumeData保存當(dāng)前文件的下載信息
    //只要有了這份信息常柄,以后就可以通過(guò)這些信息來(lái)恢復(fù)下載
    [self.task cancelByProducingResumeData:^(NSData *resumeData) {
    self.partialData = resumeData;
    self.task = nil;
    }];
    }
    }
    //繼續(xù)開(kāi)始

  • (IBAction)resume:(id)sender {
    NSLog(@"resume download task");
    if (!self.task) {
    //判斷是否又已下載數(shù)據(jù),有的話就斷點(diǎn)續(xù)傳腹备,沒(méi)有就完全重新下載
    if (self.partialData) {
    //繼續(xù)下載
    //首先通過(guò)之前保存的resumeData信息,創(chuàng)建一個(gè)下載任務(wù)
    self.task = [[self createASession] downloadTaskWithResumeData:self.partialData];
    }else{
    self.task = [[self createASession] downloadTaskWithRequest:[self createARequest]];
    }
    }
    [self.task resume];

}

pragma mark NSURLSessionDownloadDelegate

//完成下載任務(wù) 保存

  • (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didFinishDownloadingToURL:(NSURL *)location
    {
    //下載成功后买喧,文件是保存在一個(gè)臨時(shí)目錄的蔗蹋,需要開(kāi)發(fā)者自己考到放置該文件的目錄
    NSLog(@"Download success for URL: %@",location.description);
    NSURL *destination = [self createDirectoryForDownloadItemFromURL:location];
    BOOL success = [self copyTempFileAtURL:location toDestination:destination];

    if(success){
    // 文件保存成功后,使用GCD調(diào)用主線程把圖片文件顯示在UIImageView中
    dispatch_async(dispatch_get_main_queue(), ^{
    UIImage *image = [UIImage imageWithContentsOfFile:[destination path]];
    self.imageView.image = image;
    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    self.imageView.hidden = NO;
    });
    }else{
    NSLog(@"Meet error when copy file");
    }
    self.task = nil;
    }

//返回下載進(jìn)度代理方法
/*
當(dāng)接收到下載數(shù)據(jù)的時(shí)候調(diào)用,可以在該方法中監(jiān)聽(tīng)文件下載的進(jìn)度
該方法會(huì)被調(diào)用多次
totalBytesWritten:已經(jīng)寫(xiě)入到文件中的數(shù)據(jù)大小
totalBytesExpectedToWrite:目前文件的總大小
bytesWritten:本次下載的文件數(shù)據(jù)大小
*/

  • (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
    didWriteData:(int64_t)bytesWritten
    totalBytesWritten:(int64_t)totalBytesWritten
    totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    {
    //刷新進(jìn)度條的delegate方法,同樣的周霉,獲取數(shù)據(jù)跟衅,調(diào)用主線程刷新UI
    double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite;
    dispatch_async(dispatch_get_main_queue(), ^{
    self.progressBar.progress = currentProgress;
    self.progressBar.hidden = NO;
    });
    }

//創(chuàng)建文件本地保存目錄
-(NSURL *)createDirectoryForDownloadItemFromURL:(NSURL *)location
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *urls = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *documentsDirectory = urls[0];
return [documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]];
}
//把文件拷貝到指定路徑
-(BOOL) copyTempFileAtURL:(NSURL *)location toDestination:(NSURL *)destination
{

NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
[fileManager removeItemAtURL:destination error:NULL];
[fileManager copyItemAtURL:location toURL:destination error:&error];
if (error == nil) {
    return true;
}else{
    NSLog(@"%@",error);
    return false;
}

}

  • (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    }

@end

2.downloadTaskWithURL內(nèi)部默認(rèn)已經(jīng)實(shí)現(xiàn)了變下載邊寫(xiě)入操作抵皱,所以不用開(kāi)發(fā)人員擔(dān)心內(nèi)存問(wèn)題
3.文件下載后默認(rèn)保存在tmp文件目錄据途,需要開(kāi)發(fā)人員手動(dòng)的剪切到合適的沙盒目錄

3??NSURLSessionDownloadTask實(shí)現(xiàn)大文件離線斷點(diǎn)下載(完整)

  • 1.關(guān)于NSOutputStream的使用
//1. 創(chuàng)建一個(gè)輸入流,數(shù)據(jù)追加到文件的屁股上
//把數(shù)據(jù)寫(xiě)入到指定的文件地址,如果當(dāng)前文件不存在,則會(huì)自動(dòng)創(chuàng)建
NSOutputStream *stream = [[NSOutputStream alloc]initWithURL:[NSURL fileURLWithPath:[self fullPath]] append:YES];

//2. 打開(kāi)流
[stream open];

//3. 寫(xiě)入流數(shù)據(jù)
[stream write:data.bytes maxLength:data.length];

//4.當(dāng)不需要的時(shí)候應(yīng)該關(guān)閉流
[stream close];

2.關(guān)于網(wǎng)絡(luò)請(qǐng)求請(qǐng)求頭的設(shè)置(可以設(shè)置請(qǐng)求下載文件的某一部分)

//1. 設(shè)置請(qǐng)求對(duì)象
//1.1 創(chuàng)建請(qǐng)求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];

//1.2 創(chuàng)建可變請(qǐng)求對(duì)象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//1.3 拿到當(dāng)前文件的殘留數(shù)據(jù)大小
self.currentContentLength = [self FileSize];

//1.4 告訴服務(wù)器從哪個(gè)地方開(kāi)始下載文件數(shù)據(jù)
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentContentLength];
NSLog(@"%@",range);

//1.5 設(shè)置請(qǐng)求
[request setValue:range forHTTPHeaderField:@"Range"];

3.NSURLSession對(duì)象的釋放

-(void)dealloc
{
//在最后的時(shí)候應(yīng)該把session釋放,以免造成內(nèi)存泄露
// NSURLSession設(shè)置過(guò)代理后,需要在最后(比如控制器銷毀的時(shí)候)調(diào)用session的invalidateAndCancel或者resetWithCompletionHandler底桂,才不會(huì)有內(nèi)存泄露
// [self.session invalidateAndCancel];
[self.session resetWithCompletionHandler:^{

    NSLog(@"釋放---");
}];

}

4??NSURLSession實(shí)現(xiàn)文件上傳

  • (IBAction)upload:(id)sender {
    NSURLSession *session = [NSURLSession sharedSession];

    /*
    第一個(gè)參數(shù):請(qǐng)求對(duì)象
    第二個(gè)參數(shù):請(qǐng)求體(要上傳的文件數(shù)據(jù))
    block回調(diào):
    NSData:響應(yīng)體
    NSURLResponse:響應(yīng)頭
    NSError:請(qǐng)求的錯(cuò)誤信息
    */
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"我沒(méi)有一個(gè)上傳的網(wǎng)址TAT"]];
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[NSData data] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

    }];

    [uploadTask resume];

}

/*
調(diào)用該方法上傳文件數(shù)據(jù)
如果文件數(shù)據(jù)很大洞就,那么該方法會(huì)被調(diào)用多次
參數(shù)說(shuō)明:
totalBytesSent:已經(jīng)上傳的文件數(shù)據(jù)的大小
totalBytesExpectedToSend:文件的總大小
*/

  • (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
    NSLog(@"%.2f",1.0 * totalBytesSent/totalBytesExpectedToSend);
    }

關(guān)于NSURLSessionConfiguration相關(guān)

01 作用:可以統(tǒng)一配置NSURLSession,如請(qǐng)求超時(shí)等
02 創(chuàng)建的方式和使用

//創(chuàng)建配置的三種方式

  • (NSURLSessionConfiguration *)defaultSessionConfiguration;
  • (NSURLSessionConfiguration *)ephemeralSessionConfiguration;
  • (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);

//統(tǒng)一配置NSURLSession
-(NSURLSession *)session
{
if (_session == nil) {

    //創(chuàng)建NSURLSessionConfiguration
    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

    //設(shè)置請(qǐng)求超時(shí)為10秒鐘
    config.timeoutIntervalForRequest = 10;

    //在蜂窩網(wǎng)絡(luò)情況下是否繼續(xù)請(qǐng)求(上傳或下載)
    config.allowsCellularAccess = NO;

    _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;

}

四.使用AFNetworking來(lái)實(shí)現(xiàn)NSURLSession網(wǎng)絡(luò)連接

//
// AFNViewController.m
// FHYNetworkHandle
//
// Created by 付寒宇 on 15/11/7.
// Copyright ? 2015年 付寒宇. All rights reserved.
//

import "AFNViewController.h"

import "FHYNetWork.h"

@interface AFNViewController ()
@property (strong, nonatomic) IBOutlet UIImageView *imageView;

@property (strong, nonatomic) IBOutlet UIProgressView *progressView;
@property (nonatomic, strong) AFURLSessionManager *manager;
@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, strong) NSData *partialData;
@end

@implementation AFNViewController

  • (void)viewDidLoad {
    [super viewDidLoad];
    [FHYNetWork startMonitoringNetworkStatus];
    self.title = [NSString stringWithFormat:@"%ld",[FHYNetWork networkReachabilityStatus]];
    // Do any additional setup after loading the view.
    }

  • (IBAction)get:(id)sender {
    [FHYNetWork handleGETWithUrlString:@"http://api.liwushuo.com/v2/banners?channel=iOS" parameters:nil
    showHuD:YES onView:self.imageView successfulBlock:^(id responseObject) {
    NSLog(@"%@",responseObject);
    } failureBlock:^(NSError *error) {
    NSLog(@"fail");
    }];
    }

  • (IBAction)post:(id)sender {
    //http://api2.pianke.me/read/columns?auth=&client=1&deviceid=BA920378-52B5-43F2-BE1A-5404120EDD7A&version=3.0.6
    NSDictionary *parameter = @{@"app_installtime":@"1444803219.182004", @"app_versions":@"4.2.2", @"channel_name":@"appStore", @"client_id":@"bt_app_ios", @"client_secret":@"9c1e6634ce1c5098e056628cd66a17a5", @"device_token":@"e7463e1072e3457122562effbab389502ce45dafccc1b05423429470873200ba", @"oauth_token":@"b5718c6bca162f4160ddf992e4a34436", @"os_versions":@"8.3", @"page":@"0", @"pagesize":@"20", @"screensize":@"640", @"show_product":@"1", @"tag_ids":@"5701,6126,757,3153", @"track_device_info":@"iPad4%2C4", @"track_deviceid":@"643DBAC3-6A76-4A19-BFC6-0BCABEE81955", @"track_user_id":@"1394370", @"type_id":@"0", @"v":@"7"};
    [FHYNetWork handlePOSTWithUrlString:@"http://open3.bantangapp.com/community/post/listByTags" parameters:parameter showHuD:YES onView:self.view successfulBlock:^(id responseObject) {
    NSLog(@"%@",responseObject);
    } failureBlock:^(NSError *error) {
    NSLog(@"failure");
    }];
    }

  • (IBAction)upload:(id)sender {
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
    } error:nil];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSProgress *progress = nil;

    NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if (error) {
    NSLog(@"Error: %@", error);
    } else {
    NSLog(@"%@ %@", response, responseObject);
    }
    }];
    [uploadTask resume];
    }

  • (IBAction)start:(id)sender {
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
    [_manager setDownloadTaskDidWriteDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDownloadTask * _Nonnull downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
    //刷新進(jìn)度條的delegate方法,同樣的范舀,獲取數(shù)據(jù)础爬,調(diào)用主線程刷新UI
    double currentProgress = totalBytesWritten/(double)totalBytesExpectedToWrite;
    dispatch_async(dispatch_get_main_queue(), ^{
    self.progressView.progress = currentProgress;
    self.progressView.hidden = NO;
    });
    }];
    NSURL *URL = [NSURL URLWithString:@"http://p1.pichost.me/i/40/1639665.png"];
    NSURLRequest *request = [NSURLRequest requestWithURL:URL];

    self.downloadTask = [_manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
    return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { NSLog(@"File downloaded to: %@", filePath);
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:filePath]];
    [self.imageView setImage:image];

    }];

    [_downloadTask resume];
    }

  • (IBAction)pause:(id)sender {
    if (_downloadTask) {
    [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
    self.partialData = resumeData;
    self.downloadTask = nil;
    }];
    }
    }

  • (IBAction)resume:(id)sender {
    if (!self.downloadTask) {
    //判斷是否又已下載數(shù)據(jù)甫贯,有的話就斷點(diǎn)續(xù)傳,沒(méi)有就完全重新下載
    if (self.partialData) {

          self.downloadTask = [_manager downloadTaskWithResumeData:_partialData progress:nil destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
              NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
              return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
          } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
              NSLog(@"File downloaded to: %@", filePath);
              UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:filePath]];
              [self.imageView setImage:image];
    
          }];
      }else{
          [self start:nil];
      }
    

    }
    [self.downloadTask resume];

}

五.封裝NSURLSession網(wǎng)絡(luò)連接

ps:參考連接以及推薦閱讀

原文:From NSURLConnection to NSURLSession https://www.objc.io/issues/5-ios7/from-nsurlconnection-to-nsurlsession/
譯文:從 NSURLConnection 到 NSURLSession http://objccn.io/issue-5-4/

原文:AFNetworking 3.0 Migration Guide https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-3.0-Migration-Guide
譯文:AFNetworking 3.0遷移指南 http://www.reibang.com/p/047463a7ce9b

end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末看蚜,一起剝皮案震驚了整個(gè)濱河市叫搁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌供炎,老刑警劉巖渴逻,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碱茁,居然都是意外死亡裸卫,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)纽竣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)墓贿,“玉大人,你說(shuō)我怎么就攤上這事蜓氨×” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵穴吹,是天一觀的道長(zhǎng)幽勒。 經(jīng)常有香客問(wèn)我,道長(zhǎng)港令,這世上最難降的妖魔是什么啥容? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任锈颗,我火速辦了婚禮,結(jié)果婚禮上咪惠,老公的妹妹穿的比我還像新娘击吱。我一直安慰自己,他們只是感情好遥昧,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布覆醇。 她就那樣靜靜地躺著,像睡著了一般炭臭。 火紅的嫁衣襯著肌膚如雪永脓。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天鞋仍,我揣著相機(jī)與錄音常摧,去河邊找鬼。 笑死凿试,一個(gè)胖子當(dāng)著我的面吹牛排宰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播那婉,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼党瓮!你這毒婦竟也來(lái)了详炬?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤寞奸,失蹤者是張志新(化名)和其女友劉穎呛谜,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體枪萄,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡隐岛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓷翻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片聚凹。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖齐帚,靈堂內(nèi)的尸體忽然破棺而出妒牙,到底是詐尸還是另有隱情,我是刑警寧澤对妄,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布湘今,位于F島的核電站,受9級(jí)特大地震影響剪菱,放射性物質(zhì)發(fā)生泄漏摩瞎。R本人自食惡果不足惜拴签,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旗们。 院中可真熱鬧蚓哩,春花似錦、人聲如沸蚪拦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)驰贷。三九已至盛嘿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間括袒,已是汗流浹背次兆。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锹锰,地道東北人芥炭。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像恃慧,于是被迫代替她去往敵國(guó)和親园蝠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容