iOS網路相關知識總結
1.關於請求NSURLRequest?
我們經常講的GET/POST/PUT等請求是指我們要向伺服器發出的NSMutableURLRequest的型別; 我們可以設定Request的URL, HTTPMethod, HTTPHeader, HTTPBody等資訊。一般發請求儘量不要使用NSURLRequest,因為它不能設定請求方式、請求超時等(總之什麼都不能設定)。通常發請求都使用NSMutableURLRequest,可以進行更多的設定。
補充1:因為NSURL不支援中文,如包含中文,必須轉碼。
如果是GET請求,URL是拼接使用者輸入而來的,極有可能包含中文,在包裝成URL前,需對拼接str進行轉碼。
而POST請求,請求引數拼接成str,然後轉成data(中文會自動轉碼),再賦值給請求體。(如果請求體包含中文,在轉成NSData之前最好還是先進行手動轉碼)。
補充2:NSMutableURLRequest.timeoutInterval = 15; 設定請求超時後,如果伺服器在15秒後還沒有給客戶端data,那麼邊取消本次請求,handerBlock中的data=nil;開始在主執行緒中執行Block中的程式碼。
2.關於請求引數?
GET請求的請求引數需要直接拼接在URL後面,而POST請求的請求引數必須先用&拼接成字串(也可用NSMutableString拼接),然後轉成NSData的形式賦值給請求體。
POST請求引數分以下2種情況:
情況1. HTTP協議規定的標準引數形式
先用NSString將所有引數用&進行拼接(@"username=123&pwd=123")然後再轉化成NSData型別的資料賦值給request.HTTPBody,才能發給伺服器。
例如:
request.HTTPMethod = @"POST";
NSData *data = [@"username=123&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = data;
情況2. 傳送json資料給伺服器
在引數非常多,且伺服器支援以JSON形式(特殊格式的data)傳送請求引數時,那麼可以將請求引數存在OC字典/可變字典中,然後使用JSONSerialization的類方法[JSONSerialization dataWithJSONObject:params]; 將OC字典轉化成JSON資料(本質還是NSData),最後賦值給request.HTTPBody發給伺服器。
注意:
A.必須使用POST才能傳送json
B.必須設定請求頭的@"Content-Type"為JSON的MIME-type:@"application/json",因為預設情況下請求頭的Content-Type是所有引數用&拼接在一起的字串轉成的data;
例如:
//1.建立POST請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://abc.com"]];
request.HTTPMethod = @"POST"; //設定POST
//2.設定請求頭(固定寫法)
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
//3.用OC字典儲存請求引數
NSDictionary *params = @{@"goods_name:":@"連衣裙",
@"goods_price":@125,
@"user_ID":@32444455
};
//4.將OC字典轉為json(特殊格式NSData)
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil];
//5.賦值給請求體
request.HTTPBody = jsonData;
3.關於傳送網路請求的工具?
我們向伺服器傳送這些請求借助的工具就是NSURLConnection、NSURLSession、ASI、AFN等工具,而這些工具在傳送建立好的NSMutableRequest時,可以採用同步或非同步2種方式.
4.關於傳送網路請求工具的同步or非同步?
同步請求:是在主執行緒中傳送網路請求,這會將主執行緒卡在[NSURLConnection sendSync];這行程式碼上,整個UI介面上的所有控制元件都無法響應使用者,這是非常糟糕的。在實際開發中,不管是登入、下載圖片/檔案都不用同步請求。
非同步請求:開啟新的執行緒進行下載,在主執行緒的只是開啟非同步執行緒程式碼,而網路請求會在非同步執行緒中傳送,故主執行緒執行完開執行緒程式碼後,不會卡頓,會繼續執行後面的程式碼。在實際開發中,所有的網路請求都會使用非同步請求,故AFN框架中的所有請求都是非同步請求。
5.關於dispatch和NSOperation?
dispatch和NSOperation都是用來開啟非同步執行緒的工具,不過它們也能同步執行(主執行緒執行)時,只要將待執行的任務新增到主佇列中,就會在主執行緒中執行。用於執行緒間通訊。
--------------------------------------------- 華麗的分割線 -----------------------------------------------
1.關於網路請求request的傳送工具:NSURLConnection、NSURLSession、ASIHTTPRequest(“HTTP終結者”,封裝CFNetworking)、AFNetworking(封裝NSURLConnection、NSURLSession;
2.NSURLConnection的常用方法:
類方法:[NSURLConnection sendSyncBlock]、 [NSURLConnection sendAsyncBlock]、 [NSURLConnection connectionWithRequest: delegate:]
3.NSURLSession的常用方法
全部總結在另一篇文章《NSURLSession常用方法總結》中,包括所有詳細的NSURLSession所有類和方法。
NSURLSession使用步驟:a.建立session b.利用session建立dataTask/downloadTask等 c.session建立的task預設是暫停的,必須調[task resume]開始任務
4.ASIHTTPRequest(“HTTP終結者”,封裝CFNetworking)、AFNetworking(封裝NSURLConnection、NSURLSession)
--------------------------------------------- 華麗的分割線 -----------------------------------------------
1.不管是URLConnection還是URLSession,只要是帶Block的請求方法(非同步請求,開發只用非同步方法),如果Block是一次性返回響應的實體data,那麼這種方法雖然在非同步執行緒傳送,但是由於伺服器的data是一次性返回的,返回data的這些方法會瞬間撐爆記憶體,故只能用於小檔案下載,千萬不能將一次性返回的data的方法用於下載大檔案。
2.不管是URLConnection還是URLSession,只要是帶Block的方法,都是直接一次性返回伺服器response的data或者data在沙盒tmp資料夾儲存的location.path,故所有帶Block的方法是不能監控檔案下載進度的。但AFN除外,而AFN將代理方法返回的值傳到了主執行緒的block而已。
3.不管是URLConnection還是URLSession,只要想監控下載進度,就必須通過代理方法(發請求下載都在非同步執行緒,但是代理方法都在主執行緒呼叫,方便設定UI),而AFN將代理方法返回的值傳到了主執行緒的block而已。
4.URLConnection 和 URLSession在斷點續傳時的區別:
4.1 URLConnection 斷點續傳下載大檔案:
//1.建立一個NSInteger屬性self.currentLength,用來儲存當前已下載的總長度(單位:Bytes)
//2.在didReceiveData方法中,每次儲存和計算已下載data長度 self.currentLength += data.length;(單位:Bytes)
//3.開始和恢復下載都是新建一個連線self.conn,但與普通連線不同的是:必須手動設定request的請求頭Range
//4.暫停下載(其實是取消連線self.conn)即取消連線[self.conn cancel]; self.conn = nil;
//5.要想斷點續傳,必須設定HTTP請求的請求頭 "Range": "bytes=500-999"
//補充:設定HTTP請求request的請求頭Range:
NSString *Range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLength];
[request setValue:Range forHTTPHeaderField:@"Range"];
4.2 URLSession 斷點續傳下載大檔案(再也不用設定噁心的request請求頭Range了):
//1.建立一個NSDate屬性self.resumeData,用來儲存downloadTask被取消時留下的遺言resumeData(裡面包含下次恢復下載時,從哪個url和哪個Bytes開始下載)
//2.開始下載需懶載入self.session,然後task = [self.session downloadTaskWithRequest:request]; 再次[task resume];開始下載
//3.暫停下載(其實是取消task),但必須呼叫cancelByProducingResumeData-Block,並在block中儲存resumeData
//4.恢復下載(其實是用特殊方法新建任務): task = [self.session downloadTaskWithResumeData:self.resumeData]; [task resume]; self.downloadTask = task; //將task儲存起來,已便下次取消使用
//補充:第3步暫停下載的關鍵程式碼:
__weak typeof(self) vc = self; //self擁有downloadTask,而downloadTask裡面有呼叫self.resumeData,強引用self
[vc.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
vc.resumeData = resumeData; //用於下次恢復時使用
}];
vc.downloadTask = nil; //取消後,沒必要保留,下次還要建立新的task
文章系作者原創,轉載請註明出處:http://www.cnblogs.com/stevenwuzheng/p/5619182.html
如有錯誤,歡迎隨時指正!