Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 558|回复: 0

[默认分类] iOS开发网络篇—NSURLConnection基本使用

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

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

    模拟器情况:

    打印服务器返回的信息:



    补充说明:


    1.提前的表单验证


    2.发送请求给服务器(带上账号和密码)


    GET请求:请求行\请求头\请求体


    注意:GET请求中不存在请求体,因为所有的信息都写在URL里面。在IOS里面,请求行和请求头都不用写。


      


    (3)发送异步请求



      发送异步请求有两种方式:


      1)使用block回调


      2)代理


      A.使用block回调方法发送异步请求


      使用block回调代码示例:


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



    代码说明:


    block代码段:当服务器有返回数据的时候调用会开一条新的线程去发送请求,主线程继续往下走,当拿到服务器的返回数据的数据的时候再回调block,执行block代码段。这种情况不会卡住主线程。


    队列的作用:决定这个block操作放在哪个线程执行?


    刷新UI界面的操作应该放在主线程执行,不能放在子线程,在子线程处理UI相关操作会出现一些莫名的问题。


    提示:


    (1)创建一个操作,放在NSOperation队列中执行,默认是异步执行的。


    (2)mainqueue   返回一个和主线程相关的队列,即主队列。


      


    新的问题:如果向服务器发送请求,却并没有拿到数据,那么程序会崩溃(data不能为空)


    改进代码:



    1. 1  NSOperationQueue *queue=[NSOperationQueue mainQueue];
    2. 2     [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    3. 3         //当请求结束的时候调用(有两种结果,一个是成功拿到数据,也可能没有拿到数据,请求失败)
    4. 4         NSLog(@"--block回调数据--%@---%d", [NSThread currentThread],data.length);
    5. 5         //隐藏HUD,刷新UI的操作一定要放在主线程执行
    6. 6         [MBProgressHUD hideHUD];
    7. 7         
    8. 8         //解析data
    9. 9         /*
    10. 10         {"success":"登录成功"}
    11. 11         {"error":"用户名不存在"}
    12. 12         {"error":"密码不正确"}
    13. 13          */
    14. 14         if (data) {//请求成功
    15. 15             NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
    16. 16             NSLog(@"%@",dict);
    17. 17            
    18. 18             //判断后,在界面提示登录信息
    19. 19             NSString *error=dict[@"error"];
    20. 20             if (error) {
    21. 21                 [MBProgressHUD showError:error];
    22. 22             }else
    23. 23             {
    24. 24                 NSString *success=dict[@"success"];
    25. 25                 [MBProgressHUD showSuccess:success];
    26. 26             }
    27. 27         }else   //请求失败
    28. 28         {
    29. 29             [MBProgressHUD showError:@"网络繁忙,请稍后重试!"];
    30. 30         }
    31. 31      
    32. 32     }];
    复制代码



    解析data



    1.    //解析data
    2.         /*
    3.         {"success":"登录成功"}
    4.         {"error":"用户名不存在"}
    5.         {"error":"密码不正确"}
    6.          */
    复制代码



    说明:使用NSJSONSerialization 返回的对象,取决于最外层是什么,如果是{}那就是字典,[]那就是数组等。


    补充说明:


    首先确定请求路径,然后创建请求对象(默认发送的时get请求),使用异步方法(一调用这个方法,它会自动开启一个子线程去发送请求,当请求成功,数据返回的时候自动调用内部的代码段,这个代码段在那个线程执行取决于队列,如果是主队列,那么在子线程发送请求成功拿到服务器的数据后,回到主线程中解析数据,刷新UI界面)。


      


    B.使用代理方法发送异步请求


    要监听服务器返回的data,所以使用<NSURLConnectionDataDelegate>协议
    常见大代理方法如下:

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

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

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

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-20 04:02 , Processed in 0.414683 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表