基本使用
-
通過NSURLConnection發(fā)送請求常用的類
- NSURL : 用于創(chuàng)建網(wǎng)絡(luò)請求地址
- NSURLRequest : 一個(gè)NSURLRequest對象就代表一個(gè)請求
包含的信息如下:
1. 一個(gè)NSURL對象
2.請求方法,請求體,請求頭
3.請求超時(shí)
...... - NSURLConnection的作用:
1.負(fù)責(zé)發(fā)送請求,簡歷客戶端與服務(wù)器之間的連接
2.發(fā)送數(shù)據(jù)給服務(wù)器,并收集來自服務(wù)器的響應(yīng)數(shù)據(jù)
-
NSURLConnection的使用步驟
1.創(chuàng)建一個(gè)NSURL對象
2.通過創(chuàng)建的NSURL對象,創(chuàng)建一個(gè)NSURLRequest請求對象,并設(shè)置請求頭和請求體
3.定義一個(gè)響應(yīng)對象, 直接賦值為 nil 用于接收響應(yīng)的數(shù)據(jù)
一般使用 NSURLResponse 的子類 NSHTTPURLResponse
3.使用NSURLConnection發(fā)送請求
-
NSURLConnection發(fā)送請求的常見的集中方式
1.同步請求(GET-SendSync)
2.異步請求(GET-SendAsync)
3.異步請求(GET-代理)
4.發(fā)送POST請求-
同步GET請求
方法 :sendSynchronousRequest:request returningResponse:&response error:
**參數(shù)解析 : **
第一個(gè)參數(shù): 是請求對象
第二個(gè)參數(shù): 是接收響應(yīng)對象的地址 NSURLConnection同步請求就只有這個(gè)方法, 該方法是有返回值的, 返回值類型 NSData
**注意 : **阻塞式的方法,會卡住線程
-
同步GET請求
-(void)sendSync
{
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=XML"];
//2.創(chuàng)建一個(gè)請求對象
//該方法內(nèi)部會提供一個(gè)默認(rèn)的請求頭信息 | 默認(rèn)發(fā)送的就是GET請求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.把請求發(fā)送給服務(wù)器
//設(shè)置響應(yīng)對象 NSHTTPURLResponse是NSURLResponse的子類
NSHTTPURLResponse *response = nil;
NSError *error = nil;
/*
第一個(gè)參數(shù):請求對象
第二個(gè)參數(shù):響應(yīng)頭信息,當(dāng)該方法執(zhí)行完畢之后,該參數(shù)被賦值
第三個(gè)參數(shù):錯(cuò)誤信息,如果請求失敗,則error有值
*/
//該方法是阻塞式的,會卡住線程
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//4.解析服務(wù)器返回的數(shù)據(jù)
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
}
-
異步GET請求
方法 :sendAsynchronousRequest:queue:completionHandler:NSURLConnection異步請求, 也只有這一個(gè)方法
**參數(shù)解析 : **第二個(gè)參數(shù)傳輸?shù)氖顷?duì)列, 表示的是回調(diào)是在哪個(gè)線程中回調(diào)
**注意 : **該方法不會卡住當(dāng)前線程,網(wǎng)絡(luò)請求任務(wù)是異步執(zhí)行的
-(void)sendAsync
{
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it"];
//2.創(chuàng)建一個(gè)請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.把請求發(fā)送給服務(wù)器,發(fā)送一個(gè)異步請求
/*
第一個(gè)參數(shù):請求對象
第二個(gè)參數(shù):回調(diào)方法在哪個(gè)線程中執(zhí)行,如果是主隊(duì)列則block在主線程中執(zhí)行,非主隊(duì)列則在子線程中執(zhí)行
第三個(gè)參數(shù):completionHandlerBlock塊:接受到響應(yīng)的時(shí)候執(zhí)行該block中的代碼
response:響應(yīng)頭信息
data:響應(yīng)體
connectionError:錯(cuò)誤信息,如果請求失敗,那么該參數(shù)有值
*/
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {
//請求失敗返回的connectionError才會有值,不是看輸入的用戶名和密碼是不是正確
if (connectionError == nil) {
//4.解析服務(wù)器返回的數(shù)據(jù)
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//轉(zhuǎn)換并打印響應(yīng)頭信息
NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
NSLog(@"--%zd---%@--",r.statusCode,r.allHeaderFields);
}
}];
}
-
異步請求(GET-代理)
**方法一 : **一個(gè)類方法創(chuàng)建對象, 設(shè)置代理,并自動開啟請 求connectionWithRequest:delegate:
**方法二 : **有兩個(gè) alloc / initWithRequest...創(chuàng)建方法
alloc / initWithRequest: delegate:需要手動調(diào)用 start 開 啟網(wǎng)絡(luò)請求
alloc / initWithRequest: delegate: startImmediately:
第二個(gè)alloc / init是根據(jù)最后一 個(gè)參數(shù)的Bool值, 如果為 YES, 則馬上自行開啟網(wǎng)絡(luò)請求, 如果為 NO 則也是要手動調(diào)用 start-
可以設(shè)置代理方法在哪個(gè)線程中執(zhí)行
通過- setDelegateQueue:對象方法, 設(shè)置這只代理在哪個(gè)線程中執(zhí)行; 默認(rèn)情況下,代理方法會在主線程中進(jìn)行調(diào)用(為了方便開發(fā)者拿到 數(shù)據(jù)后處理一些刷新UI的操作不需要考慮到線程間通信) - **步驟 : **
(1)確定請求路徑
(2)創(chuàng)建請求對象
(3)創(chuàng)建NSURLConnection對象并設(shè)置代理
(4)遵守NSURLConnectionDataDelegate協(xié)議,并實(shí)現(xiàn)相應(yīng)的代理方法
(5)在代理方法中監(jiān)聽網(wǎng)絡(luò)請求的響應(yīng)-(void)sendAsyncDelegate { //1.創(chuàng)建請求的url路徑 NSURL * url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520&pwd=520it&type=JSON"]; //2.創(chuàng)建請求對象 NSURLRequest * request = [NSURLRequest requestWithURL:url]; //3.設(shè)置代理發(fā)送請求 //方法一 // NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; //注意:通過這個(gè)方法設(shè)置的代理,并發(fā)送的請求,是不需要手動開啟的,方法默認(rèn)會自動開啟 //方法二 //注意:參數(shù)startImmediately如果傳的是YES,那么這個(gè)方法的效果和方法一設(shè)置代理的效果是一樣的 // 如果傳的是NO,那么就需要手動發(fā)送網(wǎng)絡(luò)請求 // NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; // [connection start];//如果不手動發(fā)送網(wǎng)絡(luò)請求,那么程序是不會有任何反應(yīng) //方式三:類工廠方法,和方式一一樣 [NSURLConnection connectionWithRequest:request delegate:self]; //取消網(wǎng)絡(luò)請求 //[conn cancel]; }- 相應(yīng)的代理方法
-
可以設(shè)置代理方法在哪個(gè)線程中執(zhí)行
1.當(dāng)接收到服務(wù)器響應(yīng)的時(shí)候調(diào)用
//第一個(gè)參數(shù)connection:監(jiān)聽的是哪個(gè)NSURLConnection對象
//第二個(gè)參數(shù)response:接收到的服務(wù)器返回的響應(yīng)頭信息
- (void)connection:(nonnull NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response
2.當(dāng)接收到數(shù)據(jù)的時(shí)候調(diào)用,該方法會被調(diào)用多次
//第一個(gè)參數(shù)connection:監(jiān)聽的是哪個(gè)NSURLConnection對象
//第二個(gè)參數(shù)data:本次接收到的服務(wù)端返回的二進(jìn)制數(shù)據(jù)(可能是片段)
- (void)connection:(nonnull NSURLConnection *)connection didReceiveData:(nonnull NSData *)data
3.當(dāng)服務(wù)端返回的數(shù)據(jù)接收完畢之后會調(diào)用
//通常在該方法中解析服務(wù)器返回的數(shù)據(jù)
-(void)connectionDidFinishLoading:(nonnull NSURLConnection *)connection
4.當(dāng)請求錯(cuò)誤的時(shí)候調(diào)用(比如請求超時(shí))
//第一個(gè)參數(shù)connection:NSURLConnection對象
//第二個(gè)參數(shù):網(wǎng)絡(luò)請求的錯(cuò)誤信息,如果請求失敗,則error有值
- (void)connection:(nonnull NSURLConnection *)connection didFailWithError:(nonnull NSError *)error
- **補(bǔ)充 : **
字符串截取相關(guān)方法
- (NSRange)rangeOfString:(NSString *)searchString;
- (NSString *)substringWithRange:(NSRange)range;
-
發(fā)送POST請求
- **步驟 : **
a.確定URL路徑
b.創(chuàng)建請求對象(可變對象 ,因?yàn)橹挥性诳勺儗ο笙?才能修改請求對象的請求方法)
c.修改請求對象的方法為POST(POST必須大寫)
1.通過HTTPMethod 屬性, 修改請求對象的方法為POST<必須大寫>
2.設(shè)置請求頭部信息
3.timeoutInterval 屬性, 請求響應(yīng)等待時(shí)間(一般是15s)
d.設(shè)置請求體(Data)
1.HTTPBody 屬性, 設(shè)置請求體信息
2.字符串轉(zhuǎn)為(二進(jìn)制)編碼格式
3.type=JSON 可以不傳, 不傳默認(rèn)就是 JSON 格式, 開發(fā)中最好都寫上
e.發(fā)送一個(gè)異步請求
"sendAsynchronousRequest: queue:"
1.同步和異步各自只有一個(gè)類方法, 發(fā)送請求
2.該方法第二個(gè)參數(shù): 隊(duì)列,只是決定后面的第三個(gè)參數(shù) block塊, 在哪個(gè) 線程中回調(diào)
f.解析數(shù)據(jù)(解析的是響應(yīng)體 data 的數(shù)據(jù)) 將二進(jìn)制數(shù)據(jù)轉(zhuǎn)字符串
- **步驟 : **
-(void)post{
//1.創(chuàng)建訪問餓url路徑
//注意:以POST方式發(fā)送的請求的url沒有"?"
NSURL * url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
//2.創(chuàng)建請求體
//注意:要是想要設(shè)置發(fā)送請求方式為POST,就需要是可變的request
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
//2.1設(shè)置發(fā)送請求的方式為POST
request.HTTPMethod = @"POST";
//2.2設(shè)置請求體
request.HTTPBody = [@"username=520it&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//2.3設(shè)置請求時(shí)間
request.timeoutInterval = 15;
//2.4設(shè)置請求頭中的信息
// [request setValue:@"iOS 10.1" forHTTPHeaderField:@"User-Agent"];
//3.發(fā)送請求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.解析服務(wù)器返回的數(shù)據(jù)
if (connectionError) {
NSLog(@"--請求失敗-");
}else{
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}
}];
}
URL中文轉(zhuǎn)碼
**轉(zhuǎn)碼的方法 : **stringByAddingPercentEscapesUsingEncoding:
**原因 : **URL是不支持中文, 因此如果URL字符串中包含中文那么在發(fā)送請求之前需要 對URL進(jìn)行中文轉(zhuǎn)碼
**注意 : **瀏覽器中的 http 的鏈接有時(shí)候可以看到有中文, 其實(shí)URL內(nèi)部已經(jīng)做了轉(zhuǎn) 碼處理
**如何對URL進(jìn)行轉(zhuǎn)碼 : **stringByAddingPercentEscapesUsingEncoding
**建議 : **不管有沒有中文字符, 都寫上轉(zhuǎn)碼, 這樣擴(kuò)展性比較好
//獲取url的字符串
NSString *urlStr = @"http://120.25.226.186:32812/login2?username=小碼哥&pwd=520it";
NSLog(@"%@",urlStr);
//中文轉(zhuǎn)碼操作
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",urlStr);
//根絕轉(zhuǎn)碼后的url字符串創(chuàng)建NSURL對象
NSURL *url = [NSURL URLWithString:urlStr];
NSURLConnection和Runloop
1 兩種為NSURLConnection設(shè)置代理方式的區(qū)別
//第一種設(shè)置方式:
//通過該方法設(shè)置代理,會自動的發(fā)送請求
// [[NSURLConnection alloc]initWithRequest:request delegate:self];
//第二種設(shè)置方式:
//設(shè)置代理,startImmediately為NO的時(shí)候,該方法不會自動發(fā)送請求
NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
//手動通過代碼的方式來發(fā)送請求
//注意該方法內(nèi)部會自動的把connect添加到當(dāng)前線程的RunLoop中在默認(rèn)模式下執(zhí)行
[connect start];
2 如何控制代理方法在哪個(gè)線程調(diào)用
//說明:默認(rèn)情況下,代理方法會在主線程中進(jìn)行調(diào)用(為了方便開發(fā)者拿到數(shù)據(jù)后處理一些刷新UI的操作不需要考慮到線程間通信)
//設(shè)置代理方法的執(zhí)行隊(duì)列
[connect setDelegateQueue:[[NSOperationQueue alloc]init]];
3 開子線程發(fā)送網(wǎng)絡(luò)請求的注意點(diǎn),適用于自動發(fā)送網(wǎng)絡(luò)請求模式
//在子線程中發(fā)送網(wǎng)絡(luò)請求-調(diào)用startf方法發(fā)送
-(void)createNewThreadSendConnect1
{
//1.創(chuàng)建一個(gè)非主隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//2.封裝操作,并把任務(wù)添加到隊(duì)列中執(zhí)行
[queue addOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
//2-1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=dd&pwd=ww&type=JSON"];
//2-2.創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//2-3.使用NSURLConnection設(shè)置代理,發(fā)送網(wǎng)絡(luò)請求
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
//2-4.設(shè)置代理方法在哪個(gè)隊(duì)列中執(zhí)行,如果是非主隊(duì)列,那么代理方法將再子線程中執(zhí)行
[connection setDelegateQueue:[[NSOperationQueue alloc]init]];
//2-5.發(fā)送網(wǎng)絡(luò)請求
//注意:start方法內(nèi)部會把當(dāng)前的connect對象作為一個(gè)source添加到當(dāng)前線程對應(yīng)的runloop中
//區(qū)別在于,如果調(diào)用start方法開發(fā)送網(wǎng)絡(luò)請求,那么再添加source的過程中,如果當(dāng)前runloop不存在
//那么該方法內(nèi)部會自動創(chuàng)建一個(gè)當(dāng)前線程對應(yīng)的runloop,并啟動。
[connection start];
}];
}
//在子線程中發(fā)送網(wǎng)絡(luò)請求-自動發(fā)送網(wǎng)絡(luò)請求
-(void)createNewThreadSendConnect2
{
NSLog(@"-----");
//1.創(chuàng)建一個(gè)非主隊(duì)列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//2.封裝操作,并把任務(wù)添加到隊(duì)列中執(zhí)行
[queue addOperationWithBlock:^{
//2-1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=dd&pwd=ww&type=JSON"];
//2-2.創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//2-3.使用NSURLConnection設(shè)置代理,發(fā)送網(wǎng)絡(luò)請求
//注意:該方法內(nèi)部雖然會把connection添加到runloop,但是如果當(dāng)前的runloop不存在,那么不會主動創(chuàng)建。
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
//2-4.設(shè)置代理方法在哪個(gè)隊(duì)列中執(zhí)行,如果是非主隊(duì)列,那么代理方法將再子線程中執(zhí)行
[connection setDelegateQueue:[[NSOperationQueue alloc]init]];
//2-5 創(chuàng)建當(dāng)前線程對應(yīng)的runloop,并開啟(因?yàn)檫@個(gè)方法不會自動創(chuàng)建一個(gè)線程供NSURLConnection對象發(fā)送網(wǎng)絡(luò)請求)
[[NSRunLoop currentRunLoop]run];
}];
}
