iOS開發網絡篇—NSURLConnection基本使用

iOS開發網絡篇—NSURLConnection基本使用

1、NSURLConnection的經常使用類html

(1)NSURL:請求地址面試

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

(3)NSMutableURLRequest:NSURLRequest的子類服務器

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

做爲一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是一個個人iOS交流羣:812157648,無論你是小白仍是大牛歡迎入駐 ,分享BAT,阿里面試題、面試經驗,討論技術, 你們一塊兒交流學習成長!網絡

2、NSURLConnection的使用app

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

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

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

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

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
複製代碼

模擬器狀況:

打印服務器返回的信息:

補充說明:

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
複製代碼

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

打印查看:

代碼說明:

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) {
        //當請求結束的時候調用(有兩種結果,一個是成功拿到數據,也可能沒有拿到數據,請求失敗)
        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,因此使用協議

常見大代理方法以下:

#pragma mark- NSURLConnectionDataDelegate代理方法

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

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

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

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

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

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

//請求錯誤(失敗)的時候調用(請求超時\斷網\沒有網\,通常指客戶端錯誤)

-(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
複製代碼

打印查看:

補充:

(1)數據的處理 在didReceiveData:方法中,拼接接收到的全部數據,等全部數據都拿到後,在connectionDidFinishLoading:方法中進行處理

(2)網絡延遲 在作網絡開發的時候,必定要考慮到網絡延遲狀況的處理,能夠在服務器的代碼設置一個斷點模擬。 在服務器代碼的登陸方法中設置斷點

設置請求的最大延遲

模擬器狀況:

打印查看:

3、NSMutableURLRequest

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

設置請求超時等待時間(超過這個時間就算超時,請求失敗)- (void)setTimeoutInterval:(NSTimeInterval)seconds;

設置請求方法(好比GET和POST)- (void)setHTTPMethod:(NSString *)method;

設置請求體- (void)setHTTPBody:(NSData *)data;

設置請求頭- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

原文做者:花田半畝

原文地址:www.cnblogs.com/wendingding…

相關文章
相關標籤/搜索