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