網(wǎng)絡(luò)执解,常常和多線程搞混帝洪,以前想復(fù)雜了,其實采用最簡潔的使用方式才是推薦的方式做修。
歷史
大約在2012年左右的樣子霍狰,關(guān)于iOS的網(wǎng)絡(luò)第三方庫抡草,一般有三種觀點
當時的普遍說法是ASI
已經(jīng)停止更新;AF
比較小蔗坯,使用比較簡單康震;MK
有ASI
的效率,接口和AF
一樣好用宾濒。
當時我所在的項目組選用的是MK
腿短,當然現(xiàn)在接觸的項目,網(wǎng)絡(luò)庫基本上選擇AFNetworking
绘梦。這個基本上已經(jīng)成為事實上的標準了橘忱。
另外一個比較相關(guān)的內(nèi)容是圖片的上傳和下載。AFNetworking
其實是有圖片上傳和下載相關(guān)的功能的卸奉,但是實際接觸的項目中用的非常少钝诚。SDWebImage基本上成為圖片上傳下載的事實標準。
學(xué)習(xí)資料
iOS
關(guān)于網(wǎng)絡(luò)的API
榄棵,一開始是NSURLConnection
凝颇,當前,基本上已經(jīng)過渡到NSURLSession
疹鳄,下面幾篇文章都是不錯的學(xué)習(xí)資料
iOS開發(fā)網(wǎng)絡(luò)篇—發(fā)送GET和POST請求(使用NSURLSession)
iOS開發(fā) GET拧略、POST請求方法:NSURLSession篇
數(shù)據(jù)業(yè)務(wù)
如果采用AFNetworking的話,按照網(wǎng)上的教程來瘪弓,比如iOS開發(fā)——AFNetworking框架使用詳解垫蛆,相對比較省心。
如果想自己嘗試寫的話杠茬,那么就要多考慮一些了月褥。
數(shù)據(jù)業(yè)務(wù)應(yīng)該是APP
中使用最多的場景:
(1)從后臺拿數(shù)據(jù),顯示頁面瓢喉;
(2)提交用戶數(shù)據(jù)宁赤,提交后臺處理,響應(yīng)之后更新頁面栓票。
采用GET還是POST决左,或者兩者都有?
- 從后臺拿數(shù)據(jù)走贪,顯示頁面
對于這種場景佛猛,GET
還是有優(yōu)勢的。不需要用戶提供數(shù)據(jù)坠狡,僅僅是訪問后臺继找,像普通的瀏覽器訪問網(wǎng)站一樣,用GET
完全滿足要求逃沿。
GET
訪問婴渡,可以做緩存幻锁,加快訪問速度号坡。
GET
是NSURLSession
的默認方式列肢,只要有URL
就可以舀锨,甚至連URLRequest
都不需要掏导。
- (void)getWithUrl {
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
//2.獲得會話對象
NSURLSession *session = [NSURLSession sharedSession];
//3.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
/*
第一個參數(shù):請求路徑
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應(yīng)體信息(期望的數(shù)據(jù))
response:響應(yīng)頭信息,主要是對服務(wù)器端的描述
error:錯誤信息揽乱,如果請求失敗冕末,則error有值
注意:
1)該方法內(nèi)部會自動將請求路徑包裝成一個請求對象楔脯,該請求對象默認包含了請求頭信息和請求方法(GET)
2)如果要發(fā)送的是POST請求臼予,則不能使用該方法
*/
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//5.解析數(shù)據(jù)
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@",dict);
}];
//4.執(zhí)行任務(wù)
[dataTask resume];
}
提交用戶數(shù)據(jù)鸣戴,提交后臺處理,響應(yīng)之后更新頁面
這種場景瘟栖,GET
就無能為力了葵擎,需要用到POST
方式谅阿;
僅僅URL
不夠半哟,需要用到URLRequest
;
用戶數(shù)據(jù)签餐,放在URLRequest
的HTTPBody
之中寓涨,NSString
轉(zhuǎn)NSData
,使用NSUTF8StringEncoding
編碼
URLRequest
的HTTPBody屬性氯檐,需要設(shè)置為@"POST"
URLRequest
的頭部戒良,一般都需要加一些特殊信息,用來驗證一個可信的鏈接冠摄。比如版本號糯崎,token,sign河泳,deviceID
等等POST
是無法避免的沃呢,而GET
方式可以采用和POST
一樣的方式實現(xiàn),也就是使用URLRequest
來實現(xiàn)拆挥”∷或者說,GET
方式能做的事可以用POST
方式來取代纸兔。
- (void)getWithURLRequest {
//對請求路徑的說明
//http://120.25.226.186:32812/login?username=520it&pwd=520&type=JSON
//協(xié)議頭+主機地址+接口名稱+惰瓜?+參數(shù)1&參數(shù)2&參數(shù)3
//協(xié)議頭(http://)+主機地址(120.25.226.186:32812)+接口名稱(login)+?+參數(shù)1(username=520it)&參數(shù)2(pwd=520)&參數(shù)3(type=JSON)
//GET請求汉矿,直接把請求參數(shù)跟在URL的后面以崎坊?隔開,多個參數(shù)之間以&符號拼接
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
//2.創(chuàng)建請求對象
//請求對象內(nèi)部默認已經(jīng)包含了請求頭和請求方法(GET)
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.獲得會話對象
NSURLSession *session = [NSURLSession sharedSession];
//4.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
/*
第一個參數(shù):請求對象
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應(yīng)體信息(期望的數(shù)據(jù))
response:響應(yīng)頭信息洲拇,主要是對服務(wù)器端的描述
error:錯誤信息奈揍,如果請求失敗痹届,則error有值
*/
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil) {
//6.解析服務(wù)器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的,因此使用NSJSONSerialization進行反序列化處理)
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@",dict);
}
}];
//5.執(zhí)行任務(wù)
[dataTask resume];
}
數(shù)據(jù)業(yè)務(wù)統(tǒng)一為POST
是推薦做法打月。引入GET
队腐,反而要區(qū)分兩種方式,更麻煩奏篙。另外柴淘,POST
的安全性要比GET
高一點。
回調(diào)方式采用delegate還是block秘通?NSURLSession采用系統(tǒng)的單例還是自定義的为严?
數(shù)據(jù)業(yè)務(wù),大多數(shù)的場景是開始網(wǎng)絡(luò)操作肺稀,然后轉(zhuǎn)菊花第股,數(shù)據(jù)來了之后,更新頁面话原∠ξ牵基本上是一個異步轉(zhuǎn)同步的使用方式。 當然繁仁,如果不愿意等涉馅,可以直接頁面返回,取消這個網(wǎng)絡(luò)操作黄虱。
delegate
的方式可以提供更精確的控制稚矿,比如連接開始,連接成功捻浦,成功返回晤揣,等等,提供的系統(tǒng)函數(shù)還是比較多的朱灿。block
的方式就比較直接了昧识,開始請求,然后異步返回結(jié)果母剥。如果成功滞诺,給相應(yīng)數(shù)據(jù);如果失敗环疼,給錯誤信息习霹。系統(tǒng)默認的超時時間是
60s
,如果要更改炫隶,那么就需要自定義NSURLSession
系統(tǒng)的單例
NSURLSession
淋叶,是默認模式;如果要配置為及時模式和后臺模式伪阶,需要進行自定義煞檩。
結(jié)合需求場景处嫌,數(shù)據(jù)業(yè)務(wù),采用系統(tǒng)默認的單例NSURLSession
就可以了斟湃。采用NSURLSessionDataTask
的block
回調(diào)方式熏迹。采用delegate
方式過于復(fù)雜,沒有必要
// 1.創(chuàng)建一個網(wǎng)絡(luò)路徑
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://172.16.2.254/php/phonelogin?yourname=%@&yourpas=%@&btn=login",yourname,yourpass]];
// 2.創(chuàng)建一個網(wǎng)絡(luò)請求
NSURLRequest *request =[NSURLRequest requestWithURL:url];
// 3.獲得會話對象
NSURLSession *session = [NSURLSession sharedSession];
// 4.根據(jù)會話對象凝赛,創(chuàng)建一個Task任務(wù):
NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"從服務(wù)器獲取到數(shù)據(jù)");
/*
對從服務(wù)器獲取到的數(shù)據(jù)data進行相應(yīng)的處理:
*/ NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableLeaves) error:nil];
}];
// 5.最后一步注暗,執(zhí)行任務(wù)(resume也是繼續(xù)執(zhí)行):
[sessionDataTask resume];
下載業(yè)務(wù)
一般情況,下載業(yè)務(wù)涉及得很少墓猎,可以不提供
要用到下載捆昏,一般會認為時間比較長,文件比較大
下載一般是異步的毙沾,并且不需要轉(zhuǎn)菊花骗卜,只要顯示一個進度條就可以了
斷點續(xù)傳也是一個比較多的需求
切換到后臺,是否可以繼續(xù)下載左胞,看具體需求場景寇仓。最好不要這樣做。因為這塊目前功能還比較弱罩句,問題比較多焚刺,使用也比較麻煩
下載業(yè)務(wù)采用自定的NSURLSession
敛摘,不用系統(tǒng)的單例门烂。采用delegate
方式,不用block
方式兄淫。模式仍然采用默認的屯远,不考慮及時模式和背景模式。使用NSURLSessionDownloadTask
圖片上傳和下載
大圖的上傳和下載一般比較少捕虽,可以不做重點考慮
一般圖片大小限制在
K
級別慨丐,上M
的就應(yīng)該考慮切分和壓縮。等待時間應(yīng)當限制在10s
以內(nèi)泄私。圖片沒下載下來之前房揭,一般會提供一張默認圖片,下載完成后替換
有些場景晌端,圖片下載過程可以提供一個轉(zhuǎn)菊花捅暴,下載完成后顯示
是否采用表單數(shù)據(jù)那個
API
,可以根據(jù)情況選擇咧纠。普通的數(shù)據(jù)業(yè)務(wù)蓬痒,外面會包一層JSON
。當然漆羔,圖片數(shù)據(jù)梧奢,可以看做是一種NSData
的數(shù)據(jù)成員狱掂,也是完全可以當做一種普通的數(shù)據(jù)業(yè)務(wù)的。目前見到的實現(xiàn)方式亲轨,采用表單數(shù)據(jù)的居多趋惨。不過個人偏向統(tǒng)一為普通的數(shù)據(jù)業(yè)務(wù)。同時也不贊成一次傳好幾張圖片的方式惦蚊,一張張傳希柿,多調(diào)用幾次接口不就好了。這樣可以統(tǒng)一接口养筒。
當然曾撤,一般圖片資源服務(wù)器和后臺數(shù)據(jù)服務(wù)器的URL地址是不一樣的。不過這不構(gòu)成圖片上傳下載使用特殊接口的理由晕粪。
圖片的上傳下載挤悉,看做是普通數(shù)據(jù)業(yè)務(wù),也采用NSURLSessionDataTask
巫湘。使用block
的方式装悲,沒有必要采用delegate
。不需要考慮NSURLSessionUploadTask
和NSURLSessionDownloadTask
上傳業(yè)務(wù)
這個遇到的比較少尚氛,可以暫時不考慮诀诊。當然,想百度網(wǎng)盤那種應(yīng)用阅嘶,這個是重點了属瓣。一般情況,不需要考慮NSURLSessionUploadTask
這種場景讯柔。
小結(jié)
通過POST方式抡蛙,用好
NSURLSessionDataTask
,解決普通數(shù)據(jù)業(yè)務(wù)就可以了魂迄。只是圖片的上傳下載粗截,看做是普通的
NSURLSessionDataTask
就可以了。NSURLSessionUploadTask
和NSURLSessionDownloadTask
基本不用考慮捣炬。一般用系統(tǒng)提供的單例
NSURLSession
就可以了熊昌,沒有必要自定義。用block
的回調(diào)方式就可以了湿酸,這個方便婿屹,沒有必要用delegate
用AFNetworking和SDWebImage這兩個第三方庫當然支持,省心稿械。
NSURLSession
本來就是多線程选泻,異步的,再工作者線程中完成耗時工作,不需要再考慮NSOperation
和GCD
等多線程技術(shù)页眯。采用最簡潔的使用方式才是可取的梯捕。至于任務(wù)管理,直接使用
NSURLSessionDataTask
就可以了窝撵,本身就有id
屬性傀顾,不需要額外管理了。