iOS·HTTP那點事(1)NSURLConnection

參考文獻:

Dome地址

WeatherDome:https://github.com/BigTortoise/WeatherDome

注意:

本文以http://www.k780.com/api/weather.future# 天氣預(yù)報API接口為例敞映,展示NSURLConnection的GET和POST請求恩商。

1.iOS網(wǎng)絡(luò)層HTTP請求常用的庫:

  • 蘋果原生
    • NSURLConnection:最古老最經(jīng)典最直接的一種方案
    • NSURLSession:功能比NSURLConnection更加強大尤蒿,蘋果目前比較推薦使用這種技術(shù)(iOS7開始出的技術(shù))
  • 第三方框架
    • AFNetworking:簡單易用,提供了基本夠用的常用功能萍嬉,維護和使用者多
    • ASIHttpRequest:外號“HTTP終結(jié)者”乌昔,功能極其強大,可惜早已停止更新

2.HTTP通信過程

  • 請求
  • 請求頭:包含了對客戶端的環(huán)境描述壤追、客戶端請求信息等
    GET /minion.png HTTP/1.1 //包含了請求方法磕道、請求資源路徑、HTTP協(xié)議版本 Host: 120.25.226.186:32812 //客戶端想訪問的服務(wù)器主機地址 User-Agent: Mozilla/5.0 //客戶端的類型行冰,客戶端的軟件環(huán)境 Accept: text/html,*/* //客戶端所能接收的數(shù)據(jù)類型 Accept-Language: zh-cn //客戶端的語言環(huán)境 Accept-Encoding: gzip //客戶端支持的數(shù)據(jù)壓縮格式
  • 請求體:客戶端發(fā)給服務(wù)器的具體數(shù)據(jù)溺蕉,比如文件數(shù)據(jù)(POST請求才會有)
  • 相應(yīng)
    • 響應(yīng)頭:包含了對服務(wù)器的描述、對返回數(shù)據(jù)的描述
      HTTP/1.1 200 OK //包含了HTTP協(xié)議版本悼做、狀態(tài)碼疯特、狀態(tài)英文名稱 Server:Apache-Coyote/1.1 //服務(wù)器的類型 Content-Type: image/jpeg //返回數(shù)據(jù)的類型 Content-Length: 56811 //返回數(shù)據(jù)的長度 Date: Mon, 23 Jun2014 12:54:52 GMT //響應(yīng)的時間
  • HTTP通信過程示意圖


    HTTP通信過程.png
  • 常見響應(yīng)狀態(tài)碼


    常見響應(yīng)狀態(tài)碼.png

3.NSURLConnection常用類

  • NSURL:請求地址
  • NSURLRequest:一個NSURLRequest對象就代表一個請求,它包含的信息有
  • 一個NSURL對象
  • 請求方法肛走、請求頭漓雅、請求體
  • 請求超時
  • ……
  • NSMutableURLRequest:NSURLRequest的子類
  • NSURLConnection
    • 負責(zé)發(fā)送請求,建立客戶端和服務(wù)器的連接
    • 發(fā)送數(shù)據(jù)給服務(wù)器朽色,并收集來自服務(wù)器的響應(yīng)數(shù)據(jù)

4.GET和POST請求

  • GET

    • 所有參數(shù)拼接在URL后面邻吞,并且參數(shù)之間用&隔開
    • 沒有請求體
    • 一般用來查詢數(shù)據(jù)
  • POST

    • 所有參數(shù)都放在請求體
    • 一般用來修改、增加葫男、刪除數(shù)據(jù)
  • NSURLConnection創(chuàng)建GET和POST請求

  • GET

// 請求路徑
NSString *urlString = @"http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json";
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

// 創(chuàng)建URL
NSURL *url = [NSURL URLWithString:urlString];

// 創(chuàng)建請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 設(shè)置請求方法(默認就是GET請求)
request.HTTPMethod = @"GET";
  • POST
// 請求路徑
NSString *urlString = @"http://520it.com/圖片";
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

// 創(chuàng)建URL
NSURL *url = [NSURL URLWithString:urlString];

// 創(chuàng)建請求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 設(shè)置請求方法
request.HTTPMethod = @"POST";

// 設(shè)置請求體
request.HTTPBody = [@"name=張三&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];

5.NSURLConnection的使用步驟

  • 發(fā)送同步請求
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
// 這個方法是阻塞式的抱冷,會在當(dāng)前線程發(fā)送請求
// 當(dāng)服務(wù)器的數(shù)據(jù)完全返回時,這個方法才會返回梢褐,代碼才會繼續(xù)往下執(zhí)行
  • 發(fā)送異步請求-block
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
                          queue:(NSOperationQueue*) queue
              completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler;
// 會自動開啟一個子線程去發(fā)送請求
// 當(dāng)請求完畢(成功\失斖凇),會自動調(diào)用handler這個block
// handler這個block會放到queue這個隊列中執(zhí)行
  • 發(fā)送異步請求-delegate
  • 創(chuàng)建NSURLConnection對象
// startImmediately==YES利职,創(chuàng)建完畢后趣效,自動發(fā)送異步請求
- (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;
- (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate; // 創(chuàng)建完畢后,自動發(fā)送異步請求
+ (NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate; // 創(chuàng)建完畢后猪贪,自動發(fā)送異步請求
  • 發(fā)送請求
[connection start];
  • 遵守NSURLConnectionDataDelegate協(xié)議跷敬,實現(xiàn)協(xié)議中的代理方法
// 當(dāng)接收到服務(wù)器的響應(yīng)時就會調(diào)用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

// 每當(dāng)接收到服務(wù)器返回的數(shù)據(jù)時就會調(diào)用1次(數(shù)據(jù)量大的時候,這個方法就會被調(diào)用多次)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

// 當(dāng)服務(wù)器的數(shù)據(jù)完全返回時調(diào)用(服務(wù)器的數(shù)據(jù)接收完畢)
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

// 當(dāng)請求失敗的時候調(diào)用
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
  • 取消請求
[connection cancel];

6.NSString和NSData的互相轉(zhuǎn)換

  • NSString -> NSData
NSData *data = [@"520it.com" dataUsingEncoding:NSUTF8StringEncoding];
  • NSData -> NSString
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  //發(fā)送請求給服務(wù)器热押,加載右側(cè)的數(shù)據(jù)
        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        params[@"a"] = @"list";
        params[@"c"] = @"subscribe";
        params[@"category_id"] =@(c.id);
        [[AFHTTPSessionManager manager] GET:@"http://api.budejie.com/api/api_open.php" parameters:params success:^(NSURLSessionDataTask *task, id responseObject) {
            //字典轉(zhuǎn)模型數(shù)組
           NSArray *users = [XJQRecommendUser objectArrayWithKeyValuesArray:responseObject[@"list"]];

            //添加當(dāng)前類別對應(yīng)的用戶組
            [c.users addObjectsFromArray:users];
            //刷新表格
            [self.detailVC reloadData];

        } failure:^(NSURLSessionDataTask *task, NSError *error) {
            [SVProgressHUD showErrorWithStatus:@"加載數(shù)據(jù)失敗"];
        }];

7.Dome演示

  • Get同步和異步的兩個方法
//同步請求
- (void)sync
{
    // 請求路徑
    NSURL *url = [NSURL URLWithString:@"http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json"];
    // 創(chuàng)建請求對象
    NSURLRequest *reuqest = [[NSURLRequest alloc] initWithURL:url];
    
    // 發(fā)送請求
    // sendSynchronousRequest阻塞式的方法西傀,等待服務(wù)器返回數(shù)據(jù)
    NSHTTPURLResponse *response = nil;
    NSError *error = nil;
    NSData *data = [NSURLConnection sendSynchronousRequest:reuqest returningResponse:&response error:&error];
    
    // 解析服務(wù)器返回的數(shù)據(jù)
    NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"---%@", string);  
}


// 異步請求
- (void)async
{
    // 請求路徑
    NSURL *url = [NSURL URLWithString:@"http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json"];
    // 創(chuàng)建請求對象
    NSURLRequest *reuqest = [[NSURLRequest alloc] initWithURL:url];
    
    // 發(fā)送請求
    [NSURLConnection sendAsynchronousRequest:reuqest queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        // 解析服務(wù)器返回的數(shù)據(jù)
        NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@", string);
    }];
}
  • Post請求
- (void)asyncPost
{
    // 請求路徑
    NSURL *url = [NSURL URLWithString:@"http://api.k780.com:88"];
    // 創(chuàng)建請求對象
    NSMutableURLRequest *reuqest = [[NSMutableURLRequest alloc] initWithURL:url];
    // 更改請求方法
    reuqest.HTTPMethod = @"POST";
    // 設(shè)置請求體
    reuqest.HTTPBody = [@"app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json" dataUsingEncoding:NSUTF8StringEncoding];
    //設(shè)置請求超時
    reuqest.timeoutInterval = 3;
    // 設(shè)置請求頭
    // [request setValue:@"iOS 9.0" forHTTPHeaderField:@"User-Agent"];
    // 發(fā)送請求
    [NSURLConnection sendAsynchronousRequest:reuqest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        if (connectionError) { // 比如請求超時
            NSLog(@"----請求失敗");
        } else {
            NSLog(@"------%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        }
    }];
    
}
  • 請求運行結(jié)果:
運行結(jié)果.png

應(yīng)用程序安全運輸了明文HTTP協(xié)議(http:/ /)資源負載是不安全的。暫時的異惩把ⅲ可以通過您的應(yīng)用程序的Info.plist文件配置拥褂。

解決辦法:在iOS9 beta1中,蘋果將原h(huán)ttp協(xié)議改成了https協(xié)議牙寞,使用 TLS1.2 SSL加密請求數(shù)據(jù)饺鹃。

在info.plist中添加
<key>NSAppTransportSecurity</key><dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/></dict>
  • 修改后運行結(jié)果:
正確運行結(jié)果.png
  • 代理方法
- (void)delegateAysnc
{
    // 0.請求路徑
    NSURL *url = [NSURL URLWithString:@"http://api.k780.com:88/?app=weather.future&weaid=1&&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json"];
    
    // 1.創(chuàng)建請求對象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    // 2.創(chuàng)建連接對象
    //    [[NSURLConnection alloc] initWithRequest:request delegate:self];
    
    //    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    //    [conn start];
    
    [NSURLConnection connectionWithRequest:request delegate:self];
    
    // 取消
    //    [conn cancel];
}

#pragma mark - <NSURLConnectionDataDelegate> -- being
/**
 * 接收到服務(wù)器的響應(yīng)
 */
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

    NSLog(@"didReceiveResponse");
}


/**
 * 接收到服務(wù)器的數(shù)據(jù)(如果數(shù)據(jù)量比較大莫秆,這個方法會被調(diào)用多次)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 不斷拼接服務(wù)器返回的數(shù)據(jù)
       NSLog(@"didReceiveData -- %zd", data.length);
}

/**
 * 服務(wù)器的數(shù)據(jù)成功接收完畢
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"connectionDidFinishLoading");
}

8.注意點

-發(fā)送Get請求時可能Url中會有中文,所有最好進行一次轉(zhuǎn)碼:

NSURL *url = [NSURL URLWithString:urlStr];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末悔详,一起剝皮案震驚了整個濱河市镊屎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茄螃,老刑警劉巖缝驳,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異归苍,居然都是意外死亡用狱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進店門拼弃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來夏伊,“玉大人,你說我怎么就攤上這事肴敛∈鸷#” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵医男,是天一觀的道長砸狞。 經(jīng)常有香客問我,道長镀梭,這世上最難降的妖魔是什么刀森? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮报账,結(jié)果婚禮上研底,老公的妹妹穿的比我還像新娘。我一直安慰自己透罢,他們只是感情好榜晦,可當(dāng)我...
    茶點故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著羽圃,像睡著了一般乾胶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上朽寞,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天识窿,我揣著相機與錄音,去河邊找鬼脑融。 笑死喻频,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肘迎。 我是一名探鬼主播甥温,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼锻煌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了姻蚓?” 一聲冷哼從身側(cè)響起炼幔,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎史简,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肛著,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡圆兵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了枢贿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殉农。...
    茶點故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖局荚,靈堂內(nèi)的尸體忽然破棺而出超凳,到底是詐尸還是另有隱情,我是刑警寧澤耀态,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布轮傍,位于F島的核電站,受9級特大地震影響首装,放射性物質(zhì)發(fā)生泄漏创夜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一仙逻、第九天 我趴在偏房一處隱蔽的房頂上張望驰吓。 院中可真熱鬧,春花似錦系奉、人聲如沸檬贰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翁涤。三九已至,卻和暖如春瞬内,著一層夾襖步出監(jiān)牢的瞬間迷雪,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工虫蝶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留章咧,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓能真,卻偏偏與公主長得像赁严,于是被迫代替她去往敵國和親扰柠。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容