zoukankan      html  css  js  c++  java
  • iOS开发网络篇—NSURLConnection基本使用

    一、NSURLConnection的常用类

    (1)NSURL:请求地址

    (2)NSURLRequest:封装一个请求,保存发给服务器的全部数据,包括一个NSURL对象,请求方法、请求头、请求体....

    (3)NSMutableURLRequest:NSURLRequest的子类

    (4)NSURLConnection:负责发送请求,建立客户端和服务器的连接。发送NSURLRequest的数据给服务器,并收集来自服务器的响应数据

    二、NSURLConnection的使用
    1.简单说明

    使用NSURLConnection发送请求的步骤很简单

    (1)创建一个NSURL对象,设置请求路径(设置请求路径)

    (2)传入NSURL创建一个NSURLRequest对象,设置请求头和请求体(创建请求对象)

    (3)使用NSURLConnection发送NSURLRequest(发送请求)

    2.代码示例

    (1)发送请求的三个步骤:

    1.设置请求路径
    2.创建请求对象
    3.发送请求
    3.1发送同步请求(一直在等待服务器返回数据,这行代码会卡住,如果服务器,没有返回数据,那么在主线程UI会卡住不能继续执行操作)有返回值
    3.2发送异步请求:没有返回值
    说明:任何NSURLRequest默认都是get请求。
     
    (2)发送同步请求代码示例:
    复制代码
     1 //
     2 //  YYViewController.m
     3 //  01-NSURLConnection的使用(GET)
     4 //
     5 //  Created by apple on 14-6-28.
     6 //  Copyright (c) 2014年 itcase. All rights reserved.
     7 //
     8 
     9 #import "YYViewController.h"
    10 #import "MBProgressHUD+MJ.h"
    11 
    12 @interface YYViewController ()
    13 @property (weak, nonatomic) IBOutlet UITextField *username;
    14 @property (weak, nonatomic) IBOutlet UITextField *pwd;
    15 - (IBAction)login;
    16 
    17 @end
    18 
    19 @implementation YYViewController
    20 
    21 - (IBAction)login {
    22 //    1.提前的表单验证
    23     if (self.username.text.length==0) {
    24         [MBProgressHUD showError:@"请输入用户名"];
    25         return;
    26     }
    27     if (self.pwd.text.length==0) {
    28         [MBProgressHUD showError:@"请输入密码"];
    29         return;
    30     }
    31 //    2.发送请求给服务器(带上账号和密码)
    32     //添加一个遮罩,禁止用户操作
    33 //    [MBProgressHUD showMessage:@"正在努力加载中...."];
    34 //    GET请求:请求行请求头请求体
    35 //
    36 //    1.设置请求路径
    37     NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];
    38     NSURL *url=[NSURL URLWithString:urlStr];
    39 //    2.创建请求对象
    40     NSURLRequest *request=[NSURLRequest requestWithURL:url];
    41 //    3.发送请求
    42     //发送同步请求,在主线程执行
    43     NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    44     //(一直在等待服务器返回数据,这行代码会卡住,如果服务器没有返回数据,那么在主线程UI会卡住不能继续执行操作)
    45     NSLog(@"--%d--",data.length);
    46 }
    47 @end
    复制代码

    模拟器情况:

    打印服务器返回的信息:

    补充说明:
    1.提前的表单验证
    2.发送请求给服务器(带上账号和密码)
    GET请求:请求行请求头请求体
    注意:GET请求中不存在请求体,因为所有的信息都写在URL里面。在IOS里面,请求行和请求头都不用写。
     
    (3)发送异步请求
    发送异步请求有两种方式:
    1)使用block回调
    2)代理
    A.使用block回调方法发送异步请求
    使用block回调代码示例:
    复制代码
     1 //
     2 //  YYViewController.m
     3 //  01-NSURLConnection的使用(GET)
     4 //
     5 //  Created by apple on 14-6-28.
     6 //  Copyright (c) 2014年 itcase. All rights reserved.
     7 //
     8 
     9 #import "YYViewController.h"
    10 #import "MBProgressHUD+MJ.h"
    11 
    12 @interface YYViewController ()
    13 @property (weak, nonatomic) IBOutlet UITextField *username;
    14 @property (weak, nonatomic) IBOutlet UITextField *pwd;
    15 - (IBAction)login;
    16 
    17 @end
    18 
    19 @implementation YYViewController
    20 
    21 - (IBAction)login {
    22 //    1.提前的表单验证
    23     if (self.username.text.length==0) {
    24         [MBProgressHUD showError:@"请输入用户名"];
    25         return;
    26     }
    27     if (self.pwd.text.length==0) {
    28         [MBProgressHUD showError:@"请输入密码"];
    29         return;
    30     }
    31 //    2.发送请求给服务器(带上账号和密码)
    32     //添加一个遮罩,禁止用户操作
    33     [MBProgressHUD showMessage:@"正在努力加载中...."];
    34 
    35 //
    36 //    1.设置请求路径
    37     NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];
    38     NSURL *url=[NSURL URLWithString:urlStr];
    39     
    40 //    2.创建请求对象
    41     NSURLRequest *request=[NSURLRequest requestWithURL:url];
    42     
    43 //    3.发送请求
    44     //3.1发送同步请求,在主线程执行
    45 //    NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    46     //(一直在等待服务器返回数据,这行代码会卡住,如果服务器没有返回数据,那么在主线程UI会卡住不能继续执行操作)
    47     
    48     //3.1发送异步请求
    49     //创建一个队列(默认添加到该队列中的任务异步执行)
    50 //    NSOperationQueue *queue=[[NSOperationQueue alloc]init];
    51     //获取一个主队列
    52     NSOperationQueue *queue=[NSOperationQueue mainQueue];
    53     [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    54         NSLog(@"--block回调数据--%@---%d", [NSThread currentThread],data.length);
    55         //隐藏HUD,刷新UI的操作一定要放在主线程执行
    56         [MBProgressHUD hideHUD];
    57         
    58         //解析data
    59         /*
    60         {"success":"登录成功"}
    61         {"error":"用户名不存在"}
    62         {"error":"密码不正确"}
    63          */
    64         NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    65         NSLog(@"%@",dict);
    66         
    67         //判断后,在界面提示登录信息
    68         NSString *error=dict[@"error"];
    69         if (error) {
    70             [MBProgressHUD showError:error];
    71         }else
    72         {
    73             NSString *success=dict[@"success"];
    74             [MBProgressHUD showSuccess:success];
    75         }
    76     }];
    77     NSLog(@"请求发送完毕");
    78 }
    79 @end
    复制代码

    模拟器情况(注意这里使用了第三方框架):

    打印查看:

    代码说明:
    block代码段:当服务器有返回数据的时候调用会开一条新的线程去发送请求,主线程继续往下走,当拿到服务器的返回数据的数据的时候再回调block,执行block代码段。这种情况不会卡住主线程。
    队列的作用:决定这个block操作放在哪个线程执行?
    刷新UI界面的操作应该放在主线程执行,不能放在子线程,在子线程处理UI相关操作会出现一些莫名的问题。
    提示:
    (1)创建一个操作,放在NSOperation队列中执行,默认是异步执行的。
    (2)mainqueue   返回一个和主线程相关的队列,即主队列。
     
    新的问题:如果向服务器发送请求,却并没有拿到数据,那么程序会崩溃(data不能为空)
    改进代码:
    复制代码
     1  NSOperationQueue *queue=[NSOperationQueue mainQueue];
     2     [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
     3         //当请求结束的时候调用(有两种结果,一个是成功拿到数据,也可能没有拿到数据,请求失败)
     4         NSLog(@"--block回调数据--%@---%d", [NSThread currentThread],data.length);
     5         //隐藏HUD,刷新UI的操作一定要放在主线程执行
     6         [MBProgressHUD hideHUD];
     7         
     8         //解析data
     9         /*
    10         {"success":"登录成功"}
    11         {"error":"用户名不存在"}
    12         {"error":"密码不正确"}
    13          */
    14         if (data) {//请求成功
    15             NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    16             NSLog(@"%@",dict);
    17             
    18             //判断后,在界面提示登录信息
    19             NSString *error=dict[@"error"];
    20             if (error) {
    21                 [MBProgressHUD showError:error];
    22             }else
    23             {
    24                 NSString *success=dict[@"success"];
    25                 [MBProgressHUD showSuccess:success];
    26             }
    27         }else   //请求失败
    28         {
    29             [MBProgressHUD showError:@"网络繁忙,请稍后重试!"];
    30         }
    31      
    32     }];
    复制代码
    解析data
       //解析data
            /*
            {"success":"登录成功"}
            {"error":"用户名不存在"}
            {"error":"密码不正确"}
             */
    说明:使用NSJSONSerialization 返回的对象,取决于最外层是什么,如果是{}那就是字典,[]那就是数组等。
    补充说明:
    首先确定请求路径,然后创建请求对象(默认发送的时get请求),使用异步方法(一调用这个方法,它会自动开启一个子线程去发送请求,当请求成功,数据返回的时候自动调用内部的代码段,这个代码段在那个线程执行取决于队列,如果是主队列,那么在子线程发送请求成功拿到服务器的数据后,回到主线程中解析数据,刷新UI界面)。
     
    B.使用代理方法发送异步请求

    要监听服务器返回的data,所以使用<NSURLConnectionDataDelegate>协议

    常见大代理方法如下:

    复制代码
     1 #pragma mark- NSURLConnectionDataDelegate代理方法
     2 
     3 //当接收到服务器的响应(连通了服务器)时会调用
     4 
     5 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
     6 
     7 //当接收到服务器的数据时会调用(可能会被调用多次,每次只传递部分数据)
     8 
     9 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    10 
    11 //当服务器的数据加载完毕时就会调用
    12 
    13 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    14 
    15 //请求错误(失败)的时候调用(请求超时断网没有网,一般指客户端错误)
    16 
    17 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
    复制代码

    使用异步方法发送get请求的代码示例:

    复制代码
      1 //
      2 //  YYViewController.m
      3 //  01-NSURLConnection的使用(GET)
      4 //
      5 //  Created by apple on 14-6-28.
      6 //  Copyright (c) 2014年 itcase. All rights reserved.
      7 //
      8 
      9 #import "YYViewController.h"
     10 #import "MBProgressHUD+MJ.h"
     11 
     12 @interface YYViewController ()<NSURLConnectionDataDelegate>
     13 @property (weak, nonatomic) IBOutlet UITextField *username;
     14 @property (weak, nonatomic) IBOutlet UITextField *pwd;
     15 @property(nonatomic,strong)NSMutableData *responseData;
     16 - (IBAction)login;
     17 
     18 @end
     19 
     20 @implementation YYViewController
     21 
     22 - (IBAction)login {
     23 //    1.提前的表单验证
     24     if (self.username.text.length==0) {
     25         [MBProgressHUD showError:@"请输入用户名"];
     26         return;
     27     }
     28     if (self.pwd.text.length==0) {
     29         [MBProgressHUD showError:@"请输入密码"];
     30         return;
     31     }
     32 //    2.发送请求给服务器(带上账号和密码)
     33     //添加一个遮罩,禁止用户操作
     34     [MBProgressHUD showMessage:@"正在努力加载中...."];
     35 
     36 //
     37 //   2.1设置请求路径
     38     NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];
     39     NSURL *url=[NSURL URLWithString:urlStr];
     40     
     41 //   2.2创建请求对象
     42 //    NSURLRequest *request=[NSURLRequest requestWithURL:url];//默认就是GET请求
     43     //设置请求超时
     44     NSMutableURLRequest *request=[NSMutableURLRequest  requestWithURL:url];
     45     request.timeoutInterval=5.0;
     46     
     47 //   2.3.发送请求
     48  //使用代理发送异步请求(通常应用于文件下载)
     49     NSURLConnection *conn=[NSURLConnection connectionWithRequest:request delegate:self];
     50     [conn start];
     51     NSLog(@"已经发出请求---");
     52 }
     53 
     54 #pragma mark- NSURLConnectionDataDelegate代理方法
     55 /*
     56  *当接收到服务器的响应(连通了服务器)时会调用
     57  */
     58 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
     59 {
     60     NSLog(@"接收到服务器的响应");
     61     //初始化数据
     62     self.responseData=[NSMutableData data];
     63 }
     64 
     65 /*
     66 *当接收到服务器的数据时会调用(可能会被调用多次,每次只传递部分数据)
     67 */
     68 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
     69 {
     70     NSLog(@"接收到服务器的数据");
     71     //拼接数据
     72     [self.responseData appendData:data];
     73         NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]);
     74 }
     75 
     76 /*
     77  *当服务器的数据加载完毕时就会调用
     78  */
     79 -(void)connectionDidFinishLoading:(NSURLConnection *)connection
     80 {
     81     NSLog(@"服务器的数据加载完毕");
     82     //隐藏HUD
     83     [MBProgressHUD hideHUD];
     84     
     85     //处理服务器返回的所有数据
     86     NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:nil];
     87     
     88     //判断后,在界面提示登录信息
     89     NSString *error=dict[@"error"];
     90     if (error) {
     91         [MBProgressHUD showError:error];
     92     }else
     93     {
     94         NSString *success=dict[@"success"];
     95         [MBProgressHUD showSuccess:success];
     96     }
     97     NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]);
     98 }
     99 /*
    100  *请求错误(失败)的时候调用(请求超时断网没有网,一般指客户端错误)
    101  */
    102 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    103 {
    104 //     NSLog(@"请求错误");
    105     //隐藏HUD
    106     [MBProgressHUD hideHUD];
    107     [MBProgressHUD showError:@"网络繁忙,请稍后重试!"];
    108 }
    109 @end
    复制代码

    打印查看:

    补充:

    (1)数据的处理

    在didReceiveData:方法中,拼接接收到的所有数据,等所有数据都拿到后,在connectionDidFinishLoading:方法中进行处理

    (2)网络延迟

    在做网络开发的时候,一定要考虑到网络延迟情况的处理,可以在服务器的代码设置一个断点模拟。

    在服务器代码的登录方法中设置断点

    设置请求的最大延迟

     

    模拟器情况:

    打印查看:

    三、NSMutableURLRequest

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

    设置请求超时等待时间(超过这个时间就算超时,请求失败)- (void)setTimeoutInterval:(NSTimeInterval)seconds;

    设置请求方法(比如GET和POST)- (void)setHTTPMethod:(NSString *)method;

    设置请求体- (void)setHTTPBody:(NSData *)data;

    设置请求头- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

    转:http://www.cnblogs.com/wendingding/p/3813572.html

  • 相关阅读:
    Oracle常用命令大全(很有用,做笔记)
    表格驱动编程在代码中的应用
    mac 利用svn下载远程代码出现Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo.
    FAILURE: Build failed with an exception.
    There is an internal error in the React performance measurement code.Did not expect componentDidMount timer to start while render timer is still in progress for another instance
    react native TypeError network request failed
    Android向系统相册中插入图片,相册中会出现两张 一样的图片(只是图片大小不一致)
    react-native Unrecognized font family ‘Lonicons’;
    react-native SyntaxError xxxxx/xx.js:Unexpected token (23:24)
    Application MyTest has not been registered. This is either due to a require() error during initialization or failure to call AppRegistry.registerComponent.
  • 原文地址:https://www.cnblogs.com/kenshinobiy/p/4819247.html
Copyright © 2011-2022 走看看