亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS開發中使用NSURLConnection類處理網絡請求的方法

2020-07-26 03:30:36
字體:
來源:轉載
供稿:網友

NSURLConnection 作為 Core Foundation / CFNetwork 框架的 API 之上的一個抽象,在 2003 年,隨著第一版的 Safari 的發布就發布了。NSURLConnection 這個名字,實際上是指代的 Foundation 框架的 URL 加載系統中一系列有關聯的組件:NSURLRequest、NSURLResponse、NSURLProtocol、 NSURLCache、 NSHTTPCookieStorage、NSURLCredentialStorage 以及同名類 NSURLConnection。

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

在一個請求被發送到服務器之前,系統會先查詢共享的緩存信息,然后根據策略(policy)以及可用性(availability)的不同,一個已經被緩存的響應可能會被立即返回。如果沒有緩存的響應可用,則這個請求將根據我們指定的策略來緩存它的響應以便將來的請求可以使用。

在把請求發送給服務器的過程中,服務器可能會發出鑒權查詢(authentication challenge),這可以由共享的 cookie 或機密存儲(credential storage)來自動響應,或者由被委托對象來響應。發送中的請求也可以被注冊的 NSURLProtocol 對象所攔截,以便在必要的時候無縫地改變其加載行為。

不管怎樣,NSURLConnection 作為網絡基礎架構,已經服務了成千上萬的 iOS 和 Mac OS 程序,并且做的還算相當不錯。但是這些年,一些用例――尤其是在 iPhone 和 iPad 上面――已經對 NSURLConnection 的幾個核心概念提出了挑戰,讓蘋果有理由對它進行重構。

一、NSURLConnection的常用類

(1)NSURL:請求地址

(2)NSURLRequest:封裝一個請求,保存發給服務器的全部數據,包括一個NSURL對象,請求方法、請求頭、請求體....

(3)NSMutableURLRequest:NSURLRequest的子類

(4)NSURLConnection:負責發送請求,建立客戶端和服務器的連接。發送NSURLRequest的數據給服務器,并收集來自服務器的響應數據

 

二、NSURLConnection的使用
1.簡單說明
使用NSURLConnection發送請求的步驟很簡單

(1)創建一個NSURL對象,設置請求路徑(設置請求路徑)

(2)傳入NSURL創建一個NSURLRequest對象,設置請求頭和請求體(創建請求對象)

(3)使用NSURLConnection發送NSURLRequest(發送請求)

2015122795428844.png (711×228)

2.代碼示例

(1)發送請求的三個步驟:

1.設置請求路徑
2.創建請求對象
3.發送請求
3.1發送同步請求(一直在等待服務器返回數據,這行代碼會卡住,如果服務器,沒有返回數據,那么在主線程UI會卡住不能繼續執行操作)有返回值
3.2發送異步請求:沒有返回值
說明:任何NSURLRequest默認都是get請求。
 
(2)發送同步請求代碼示例:

復制代碼 代碼如下:

//
//  YYViewController.m
//  01-NSURLConnection的使用(GET)
//
//  Created by apple on 14-6-28.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import "MBProgressHUD+MJ.h"

@interface YYViewController ()
@property (weak, nonatomic) IBOutlet UITextField *username;
@property (weak, nonatomic) IBOutlet UITextField *pwd;
- (IBAction)login;

@end


復制代碼 代碼如下:

@implementation YYViewController

- (IBAction)login {
//    1.提前的表單驗證
    if (self.username.text.length==0) {
        [MBProgressHUD showError:@"請輸入用戶名"];
        return;
    }
    if (self.pwd.text.length==0) {
        [MBProgressHUD showError:@"請輸入密碼"];
        return;
    }
//    2.發送請求給服務器(帶上賬號和密碼)
    //添加一個遮罩,禁止用戶操作
//    [MBProgressHUD showMessage:@"正在努力加載中...."];
//    GET請求:請求行/請求頭/請求體
//
//    1.設置請求路徑
    NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];
    NSURL *url=[NSURL URLWithString:urlStr];
//    2.創建請求對象
    NSURLRequest *request=[NSURLRequest requestWithURL:url];
//    3.發送請求
    //發送同步請求,在主線程執行
    NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    //(一直在等待服務器返回數據,這行代碼會卡住,如果服務器沒有返回數據,那么在主線程UI會卡住不能繼續執行操作)
    NSLog(@"--%d--",data.length);
}
@end


模擬器情況:

2015122795506580.png (319×500)

打印服務器返回的信息:

2015122795525160.png (965×41)

補充說明:
1.提前的表單驗證
2.發送請求給服務器(帶上賬號和密碼)
GET請求:請求行/請求頭/請求體
注意:GET請求中不存在請求體,因為所有的信息都寫在URL里面。在IOS里面,請求行和請求頭都不用寫。
 
(3)發送異步請求
發送異步請求有兩種方式:
1)使用block回調
2)代理
A.使用block回調方法發送異步請求
使用block回調代碼示例:

復制代碼 代碼如下:

//
//  YYViewController.m
//  01-NSURLConnection的使用(GET)
//
//  Created by apple on 14-6-28.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import "MBProgressHUD+MJ.h"

@interface YYViewController ()
@property (weak, nonatomic) IBOutlet UITextField *username;
@property (weak, nonatomic) IBOutlet UITextField *pwd;
- (IBAction)login;

@end


復制代碼 代碼如下:

@implementation YYViewController

- (IBAction)login {
//    1.提前的表單驗證
    if (self.username.text.length==0) {
        [MBProgressHUD showError:@"請輸入用戶名"];
        return;
    }
    if (self.pwd.text.length==0) {
        [MBProgressHUD showError:@"請輸入密碼"];
        return;
    }
//    2.發送請求給服務器(帶上賬號和密碼)
    //添加一個遮罩,禁止用戶操作
    [MBProgressHUD showMessage:@"正在努力加載中...."];

//
//    1.設置請求路徑
    NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];
    NSURL *url=[NSURL URLWithString:urlStr];
   
//    2.創建請求對象
    NSURLRequest *request=[NSURLRequest requestWithURL:url];
   
//    3.發送請求
    //3.1發送同步請求,在主線程執行
//    NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    //(一直在等待服務器返回數據,這行代碼會卡住,如果服務器沒有返回數據,那么在主線程UI會卡住不能繼續執行操作)
   
    //3.1發送異步請求
    //創建一個隊列(默認添加到該隊列中的任務異步執行)
//    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    //獲取一個主隊列
    NSOperationQueue *queue=[NSOperationQueue mainQueue];
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        NSLog(@"--block回調數據--%@---%d", [NSThread currentThread],data.length);
        //隱藏HUD,刷新UI的操作一定要放在主線程執行
        [MBProgressHUD hideHUD];
       
        //解析data
        /*
        {"success":"登錄成功"}
        {"error":"用戶名不存在"}
        {"error":"密碼不正確"}
         */
        NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
        NSLog(@"%@",dict);
       
        //判斷后,在界面提示登錄信息
        NSString *error=dict[@"error"];
        if (error) {
            [MBProgressHUD showError:error];
        }else
        {
            NSString *success=dict[@"success"];
            [MBProgressHUD showSuccess:success];
        }
    }];
    NSLog(@"請求發送完畢");
}
@end


模擬器情況(注意這里使用了第三方框架):

2015122795603843.png (640×960)

打印查看:

20151227100255079.png (1104×129)

代碼說明:
block代碼段:當服務器有返回數據的時候調用會開一條新的線程去發送請求,主線程繼續往下走,當拿到服務器的返回數據的數據的時候再回調block,執行block代碼段。這種情況不會卡住主線程。
隊列的作用:決定這個block操作放在哪個線程執行?
刷新UI界面的操作應該放在主線程執行,不能放在子線程,在子線程處理UI相關操作會出現一些莫名的問題。
提示:
(1)創建一個操作,放在NSOperation隊列中執行,默認是異步執行的。
(2)mainqueue   返回一個和主線程相關的隊列,即主隊列。
 
新的問題:如果向服務器發送請求,卻并沒有拿到數據,那么程序會崩潰(data不能為空)
改進代碼:

復制代碼 代碼如下:

NSOperationQueue *queue=[NSOperationQueue mainQueue];
    [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        //當請求結束的時候調用(有兩種結果,一個是成功拿到數據,也可能沒有拿到數據,請求失?。?br />        NSLog(@"--block回調數據--%@---%d", [NSThread currentThread],data.length);
        //隱藏HUD,刷新UI的操作一定要放在主線程執行
        [MBProgressHUD hideHUD];
       
        //解析data
        /*
        {"success":"登錄成功"}
        {"error":"用戶名不存在"}
        {"error":"密碼不正確"}
         */
        if (data) {//請求成功
            NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
            NSLog(@"%@",dict);
           
            //判斷后,在界面提示登錄信息
            NSString *error=dict[@"error"];
            if (error) {
                [MBProgressHUD showError:error];
            }else
            {
                NSString *success=dict[@"success"];
                [MBProgressHUD showSuccess:success];
            }
        }else   //請求失敗
        {
            [MBProgressHUD showError:@"網絡繁忙,請稍后重試!"];
        }
    
    }];

解析data
復制代碼 代碼如下:

   //解析data
        /*
        {"success":"登錄成功"}
        {"error":"用戶名不存在"}
        {"error":"密碼不正確"}
         */

說明:使用NSJSONSerialization 返回的對象,取決于最外層是什么,如果是{}那就是字典,[]那就是數組等。
補充說明:
首先確定請求路徑,然后創建請求對象(默認發送的時get請求),使用異步方法(一調用這個方法,它會自動開啟一個子線程去發送請求,當請求成功,數據返回的時候自動調用內部的代碼段,這個代碼段在那個線程執行取決于隊列,如果是主隊列,那么在子線程發送請求成功拿到服務器的數據后,回到主線程中解析數據,刷新UI界面)。
 
B.使用代理方法發送異步請求
要監聽服務器返回的data,所以使用<NSURLConnectionDataDelegate>協議

常見大代理方法如下:

復制代碼 代碼如下:

#pragma mark- NSURLConnectionDataDelegate代理方法

//當接收到服務器的響應(連通了服務器)時會調用

-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

//當接收到服務器的數據時會調用(可能會被調用多次,每次只傳遞部分數據)

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

//當服務器的數據加載完畢時就會調用

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

//請求錯誤(失?。┑臅r候調用(請求超時/斷網/沒有網/,一般指客戶端錯誤)

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error


使用異步方法發送get請求的代碼示例:
復制代碼 代碼如下:

//
//  YYViewController.m
//  01-NSURLConnection的使用(GET)
//
//  Created by apple on 14-6-28.
//  Copyright (c) 2014年 itcase. All rights reserved.
//

#import "YYViewController.h"
#import "MBProgressHUD+MJ.h"

@interface YYViewController ()<NSURLConnectionDataDelegate>
@property (weak, nonatomic) IBOutlet UITextField *username;
@property (weak, nonatomic) IBOutlet UITextField *pwd;
@property(nonatomic,strong)NSMutableData *responseData;
- (IBAction)login;

@end


復制代碼 代碼如下:

@implementation YYViewController

- (IBAction)login {
//    1.提前的表單驗證
    if (self.username.text.length==0) {
        [MBProgressHUD showError:@"請輸入用戶名"];
        return;
    }
    if (self.pwd.text.length==0) {
        [MBProgressHUD showError:@"請輸入密碼"];
        return;
    }
//    2.發送請求給服務器(帶上賬號和密碼)
    //添加一個遮罩,禁止用戶操作
    [MBProgressHUD showMessage:@"正在努力加載中...."];

//
//   2.1設置請求路徑
    NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];
    NSURL *url=[NSURL URLWithString:urlStr];
   
//   2.2創建請求對象
//    NSURLRequest *request=[NSURLRequest requestWithURL:url];//默認就是GET請求
    //設置請求超時
    NSMutableURLRequest *request=[NSMutableURLRequest  requestWithURL:url];
    request.timeoutInterval=5.0;
   
//   2.3.發送請求
 //使用代理發送異步請求(通常應用于文件下載)
    NSURLConnection *conn=[NSURLConnection connectionWithRequest:request delegate:self];
    [conn start];
    NSLog(@"已經發出請求---");
}

#pragma mark- NSURLConnectionDataDelegate代理方法
/*
 *當接收到服務器的響應(連通了服務器)時會調用
 */
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"接收到服務器的響應");
    //初始化數據
    self.responseData=[NSMutableData data];
}

/*
*當接收到服務器的數據時會調用(可能會被調用多次,每次只傳遞部分數據)
*/
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"接收到服務器的數據");
    //拼接數據
    [self.responseData appendData:data];
        NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]);
}

/*
 *當服務器的數據加載完畢時就會調用
 */
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"服務器的數據加載完畢");
    //隱藏HUD
    [MBProgressHUD hideHUD];
   
    //處理服務器返回的所有數據
    NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:nil];
   
    //判斷后,在界面提示登錄信息
    NSString *error=dict[@"error"];
    if (error) {
        [MBProgressHUD showError:error];
    }else
    {
        NSString *success=dict[@"success"];
        [MBProgressHUD showSuccess:success];
    }
    NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]);
}
/*
 *請求錯誤(失敗)的時候調用(請求超時/斷網/沒有網/,一般指客戶端錯誤)
 */
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
//     NSLog(@"請求錯誤");
    //隱藏HUD
    [MBProgressHUD hideHUD];
    [MBProgressHUD showError:@"網絡繁忙,請稍后重試!"];
}
@end


打印查看:

20151227100022464.png (854×124)

補充:

(1)數據的處理

在didReceiveData:方法中,拼接接收到的所有數據,等所有數據都拿到后,在connectionDidFinishLoading:方法中進行處理

(2)網絡延遲

在做網絡開發的時候,一定要考慮到網絡延遲情況的處理,可以在服務器的代碼設置一個斷點模擬。

在服務器代碼的登錄方法中設置斷點

2015122795703957.png (587×396)

設置請求的最大延遲

2015122795721732.png (895×154)

模擬器情況:

2015122795903439.png (640×960)

打印查看:

2015122795755620.png (928×85)

三、NSMutableURLRequest

NSMutableURLRequest是NSURLRequest的子類,常用方法有

設置請求超時等待時間(超過這個時間就算超時,請求失?。?div id="avoqvkz" class="codetitle">復制代碼 代碼如下:

- (void)setTimeoutInterval:(NSTimeInterval)seconds;

設置請求方法(比如GET和POST)

復制代碼 代碼如下:
- (void)setHTTPMethod:(NSString *)method;

設置請求體

復制代碼 代碼如下:
- (void)setHTTPBody:(NSData *)data;

設置請求頭

復制代碼 代碼如下:
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

上一篇:詳解iOS中多線程app開發的GCD隊列的使用

下一篇:iOS開發中使用CoreLocation框架處理地理編碼的方法

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色黄久久久久久| 国产精品日韩欧美大师| 两个人的视频www国产精品| 亚洲第一区第一页| 97视频人免费观看| 日韩欧美黄色动漫| 亚洲免费高清视频| 国产精品一区二区久久久久| 国产精品麻豆va在线播放| 久久综合网hezyo| 欧美综合一区第一页| 国产视频久久久久| 久久av红桃一区二区小说| 欧美日在线观看| 美日韩在线视频| 九色成人免费视频| 国产视频久久久久久久| 日本久久久久亚洲中字幕| 日韩视频在线免费| 欧美极品少妇xxxxⅹ喷水| 欧美性精品220| 亚洲精品国产福利| 岛国av午夜精品| 国产亚洲成精品久久| 欧美日韩国产第一页| 国产精品一区久久| 播播国产欧美激情| 成人免费看黄网站| 亚洲欧美精品一区二区| 国产三级精品网站| 亚洲另类欧美自拍| 中日韩午夜理伦电影免费| 国产在线98福利播放视频| 视频在线观看一区二区| 久久久久久噜噜噜久久久精品| 日韩美女视频中文字幕| 91免费电影网站| 亚洲高清av在线| 国产精品久久久久久久久久尿| 色综合91久久精品中文字幕| 91精品国产自产在线老师啪| 久久中文字幕视频| 国产精品老牛影院在线观看| 国产精品亚洲欧美导航| 在线观看免费高清视频97| 国产精品久久久久久久久久免费| 欧美成人在线免费视频| 欧美中文字幕在线观看| 国产午夜精品理论片a级探花| 欧美大肥婆大肥bbbbb| 亚洲网站在线看| 欧美野外wwwxxx| 国产成人精品久久亚洲高清不卡| 中文字幕v亚洲ⅴv天堂| 亚洲精品日韩av| 97久久久久久| 亚洲精品色婷婷福利天堂| 成人黄色大片在线免费观看| 久久久免费高清电视剧观看| 精品日韩美女的视频高清| 亚洲天堂免费视频| 91久久精品久久国产性色也91| 91久久国产婷婷一区二区| 欧美成人午夜免费视在线看片| 欧美日韩午夜剧场| 国产精品高潮视频| 国内揄拍国内精品少妇国语| 国产精品色视频| 国产精品国产福利国产秒拍| 欧美精品久久久久久久久久| www欧美xxxx| 一区国产精品视频| 亚洲欧美日韩国产成人| 国内精品中文字幕| 久久久久日韩精品久久久男男| 久久综合免费视频影院| 福利一区福利二区微拍刺激| 亚洲欧美国产日韩中文字幕| 成人久久一区二区| 668精品在线视频| 国产精品一区专区欧美日韩| 日本最新高清不卡中文字幕| 国产精品一区av| 国内精品视频在线| 亚洲欧洲在线免费| 亚洲电影天堂av| 亚洲国产中文字幕在线观看| 亚洲成人免费网站| 欧美激情一区二区三区久久久| 欧美午夜片在线免费观看| 欧美日韩综合视频网址| 国产精品美女免费看| 欧美精品激情blacked18| 91av福利视频| 热99精品只有里视频精品| 日韩av免费网站| xxxxx成人.com| 亚洲久久久久久久久久| 国产精品一区二区3区| 欧美一区二区视频97| 91久久久精品| 亚洲精品动漫100p| 久久久午夜视频| 久久午夜a级毛片| 国产亚洲欧美日韩精品| 国产日韩精品入口| 成人午夜一级二级三级| 精品亚洲一区二区| 久久黄色av网站| 日韩电影中文字幕在线| 欧美另类99xxxxx| 亚洲人成绝费网站色www| 日韩视频免费大全中文字幕| 国产精品午夜一区二区欲梦| 久久久久久免费精品| 欧美午夜性色大片在线观看| 国产午夜精品一区理论片飘花| 国产成人在线亚洲欧美| 国产91精品久久久久久| 亚洲精品一区二区三区不| www.亚洲男人天堂| 欧美国产中文字幕| 日韩在线视频免费观看高清中文| 色偷偷av一区二区三区| 91欧美精品成人综合在线观看| 成年无码av片在线| 日av在线播放中文不卡| 亚洲一区二区久久久久久| 国产在线拍揄自揄视频不卡99| 欧美激情中文字幕乱码免费| 精品国产户外野外| 国产精品久久久久久久久男| 色综合天天狠天天透天天伊人| 蜜臀久久99精品久久久无需会员| 久久亚洲影音av资源网| 久久久99久久精品女同性| 国内免费久久久久久久久久久| 欧美尺度大的性做爰视频| 欧美成人黑人xx视频免费观看| 久久亚洲精品国产亚洲老地址| 国产一区二区日韩| 久久久亚洲精品视频| 亚洲日本中文字幕免费在线不卡| 精品国产老师黑色丝袜高跟鞋| 日本一区二区在线免费播放| 久久精品99久久久久久久久| 91精品91久久久久久| 亚洲国产精品中文| 欧美激情免费看| 亚洲跨种族黑人xxx| 亚洲欧美国产一本综合首页| 精品成人国产在线观看男人呻吟| 亚洲韩国日本中文字幕| 92裸体在线视频网站| www.欧美精品一二三区| 91精品久久久久久久| 日韩二区三区在线| 国产精品扒开腿做爽爽爽男男| 欧美黄色片在线观看| 精品香蕉一区二区三区| 日韩一区二区精品视频| 欧美诱惑福利视频| 国产极品精品在线观看| 亚洲免费成人av电影|