iOS基础 - 网络:Get和Post | NSURLConnection
▶ NSURLConnection
1 - NSURLConnection 已被 NSURLSession 所代替,在 WWDC2013 上 NSURLSession 随 iOS 7 一起发布,它是对 NSURLConnection 重构、优化后的新的网络访问接口。从 iOS 9.0 开始 NSURLConnection 中发送请求的两个方法已过期(同步请求、异步请求),并且初始化网络连接 initWithRequest: delegate: 方法也被置为过期,不再推荐使用
2 - 我们在开发中常用到的类
① NSURLRequest/NSMutableURLRequest:封装一个请求,用来保存发给服务器的全部数据。它包括 NSURL 对象,请求方法、请求头、请求体....
② NSURLConnection:负责发送请求、建立客户端和服务器的连接,发送 NSURLRequest 的数据给服务器,并收集来自服务器的响应数据
3 - 发送请求步骤
① 配置请求路径,就是 NSURL 对象:URL 作为网址字符串包含很多请求参数,它对网址字符串进行封装,我们可以使用 NSURL 对象获取相应的参数
② 创建请求对象,就是 NSURLRequest 对象:包含请求头和请求体
③ 发送请求:使用 NSURLConnection 发送 NSURLRequest
4 - 请求方式
① 同步请求:在主线程中完成,程序会一直在等待服务器返回数据,正在进行网络请求的代码,其后的程序代码不再执行!一旦服务器没有返回数据,那么在主线程的 UI 就会卡顿
② 异步请求:在子线程中进行,不会造成 UI 假死的问题,无网络返回数据。如果要监听服务器返回的数据,要配合 <NSURLConnectionDataDelegate> 协议使用,或者使用 Block
5 - NSMutableURLRequest
// 请求超时等待时间 - (void)setTimeoutInterval:(NSTimeInterval)seconds; // 请求方法(Get/Post) - (void)setHTTPMethod:(NSString *)method; // 请求体 - (void)setHTTPBody:(NSData *)data; // 请求头 - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
▶ Get | Post
1 - 相同点:两者均可以请求或者提交数据。Get 通常用于获取数据;Post 通常用于提交数据
2 - 不同点
① 请求的格式不一样
Get 请求接口的地址和参数之间用 ? 连接,参数与参数之间使用 & 连接,每一个参数的 键/值 用 = 连接
Post 请求是把参数转成 NSData 后放在 HttpBody 中提交给服务器
② 安全程度不一样
Get 请求可以直接看到请求的参数
Post 请求看不到请求参数
注:Get 网址字符串最多 255 字节;而 Post 使⽤ NSData,容量可超过 1G
iOS 中任何 NSURLRequest 默认都是 Get
代码示例:实现网络请求。UI 布局如下图(点击 下载图片 后的效果图)
// - ViewController.m
1 #import "ViewController.h" 2 #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 3 @interface ViewController () 4 5 @property(nonatomic,strong)NSMutableData *data; // 数据容器:存放服务器返回的数据 6 @property(nonatomic,strong)NSURLConnection *connection; 7 8 @end 9 10 @implementation ViewController 11 12 - (void)viewDidLoad { 13 14 [super viewDidLoad]; 15 self.view.backgroundColor = [UIColor cyanColor]; 16 17 // 请求按钮 18 [self addBUttonWithFrame:CGRectMake(100, 50, SCREEN_WIDTH - 200, 40) title:@"异步 Get" target:self selector:@selector(asynchronizeGet)]; 19 [self addBUttonWithFrame:CGRectMake(100, 120, SCREEN_WIDTH - 200, 40) title:@"异步 Post" target:self selector:@selector(asynchronizePost)]; 20 [self addBUttonWithFrame:CGRectMake(100, 190, SCREEN_WIDTH - 200, 40) title:@"同步 Get" target:self selector:@selector(synchronizeGet)]; 21 [self addBUttonWithFrame:CGRectMake(100, 260, SCREEN_WIDTH - 200, 40) title:@"同步 Post" target:self selector:@selector(synchronizePost)]; 22 [self addBUttonWithFrame:CGRectMake(100, 330, SCREEN_WIDTH - 200, 40) title:@"下载图片" target:self selector:@selector(downLoadImage)]; 23 24 //将要下载的图片 25 UIImageView *aImageView = [[UIImageView alloc] initWithFrame:CGRectMake(30, 400, SCREEN_WIDTH-60, 220)]; 26 aImageView.backgroundColor = [UIColor blackColor]; 27 aImageView.layer.masksToBounds = YES; 28 aImageView.layer.cornerRadius = 10; 29 aImageView.tag = 100; 30 [self.view addSubview:aImageView]; 31 } 32 33 // 创建按钮 34 - (void)addBUttonWithFrame:(CGRect)frame title:(NSString *)title target:(id)target selector:(SEL)sel{ 35 36 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; 37 button.layer.cornerRadius = 10; 38 button.frame = frame; 39 [button setTitle:title forState:UIControlStateNormal]; 40 [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 41 [button addTarget:target action:sel forControlEvents:UIControlEventTouchUpInside]; 42 button.backgroundColor = [UIColor blackColor]; 43 [self.view addSubview:button]; 44 } 45 46 // 异步 Get 47 - (void)asynchronizeGet{ 48 49 // -------------- 方式一:配合代理 ------------------ 50 // 配置请求路径 51 NSString *urlString = @"http://api.map.baidu.com/place/v2/search?query=银行®ion=郑州&output=json&ak=6E823f587c95f0148c19993539b99295"; 52 // 算是一个安全保障机制:把请求路径进行 URLEncode 编码,防止路径中含有汉字而造成编译不通过的问题 53 NSString *newUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 54 NSURL *URL = [NSURL URLWithString:newUrlString]; 55 56 // 请求对象:根据 URL 对象生成请求 57 NSURLRequest *requst = [NSURLRequest requestWithURL:URL]; 58 // 发送请求 59 [NSURLConnection connectionWithRequest:requst delegate:self]; 60 61 62 // --------------- 方式二:使用 Block ------------------ 63 NSString *urlStr_bl = [NSString stringWithFormat:@"http://api.map.baidu.com/place/v2/search?query=银行®ion=郑州&output=json&ak=6E823f587c95f0148c19993539b99295"]; 64 NSString *newUrlStr_bl = [urlStr_bl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 65 NSURL *url_bl = [NSURL URLWithString:newUrlStr_bl]; 66 NSURLRequest *request_bl = [NSURLRequest requestWithURL:url_bl]; 67 68 // 主队列 69 NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; 70 // 异步请求 71 [NSURLConnection sendAsynchronousRequest:request_bl queue:mainQueue completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { 72 73 // 简单地验证下是否拿到数据 74 if (data) { 75 NSLog(@"Get_Block:%@---%lu", [NSThread currentThread],data.length); 76 // 解析数据 77 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil]; 78 NSLog(@"Get_Block:Dic = %@",dict); 79 }else{ 80 NSLog(@"Get_Block:Error = %@",connectionError); 81 } 82 }]; 83 } 84 85 // 同步 Get 86 - (void)synchronizeGet{ 87 88 NSString *imageUrl = @"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fdik.img.kttpdq.com%2Fpic%2F69%2F47802%2Fb120a7942a39e844_1680x1050.jpg&refer=http%3A%2F%2Fdik.img.kttpdq.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639510061&t=dfb29886b6c2c1741cd4492a39e036bb"; 89 NSURL *url = [NSURL URLWithString:imageUrl]; 90 NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:3.0]; 91 // 同步请求有网络返回数据,并且任务在主线程完成,数据未下载完就不会往下执行,容易导致 UI 假死的问题 92 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 93 UIImage *aIamge = [UIImage imageWithData:data]; 94 UIImageView *imageView = (UIImageView *)[self.view viewWithTag:100]; 95 imageView.image = aIamge; 96 } 97 98 // 异步P ost 99 - (void)asynchronizePost{ 100 101 NSString *urlString = @"http://api.tudou.com/v3/gw"; 102 NSURL *url = [NSURL URLWithString:urlString]; 103 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:3.0]; 104 // 请求方式 105 [request setHTTPMethod:@"POST"]; 106 // 配置参数 107 NSString *paramString = @"method=user.item.get&appKey=43db911a75b88c11&format=json&user=ttr2008&pageNo=1&pageSize=10"; 108 NSData *paramData = [paramString dataUsingEncoding:NSUTF8StringEncoding]; 109 // 将参数放进请求体中 110 [request setHTTPBody:paramData]; 111 // 需使用代理 112 [NSURLConnection connectionWithRequest:request delegate:self]; 113 } 114 115 // 同步 Post 116 - (void)synchronizePost{ 117 118 NSString *urlString = @"http://api.tudou.com/v3/gw"; 119 NSURL *url = [NSURL URLWithString:urlString]; 120 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:3.0]; 121 [request setHTTPMethod:@"POST"]; 122 NSString *paramString =@"method=user.item.get&appKey=43db911a75b88c11&format=json&user=ttr2008&pageNo=1&pageSize=10"; 123 NSData *data = [paramString dataUsingEncoding:NSUTF8StringEncoding]; 124 [request setHTTPBody:data]; 125 NSData *resultData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 126 127 // 注:要牢记同步请求有数据返回 128 NSLog(@"同步Post的Data == %@",resultData); 129 if(resultData){ 130 NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:resultData options:0 error:nil]; 131 NSLog(@"同步Post响应数据 == %@",dic); 132 } 133 } 134 135 // 下载图片 136 - (void)downLoadImage{ 137 138 NSString *imageURLString = @"https://img0.baidu.com/it/u=2364709123,290344084&fm=253&fmt=auto&app=120&f=JPEG?w=1416&h=800"; 139 NSURL *url = [NSURL URLWithString:imageURLString]; 140 NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:3.0]; 141 // 使用代理 142 self.connection = [NSURLConnection connectionWithRequest:request delegate:self]; 143 } 144 145 146 #pragma mark - <NSURLConnectionDelegate> 147 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ 148 NSLog(@"---didReceiveResponse---"); 149 150 // 在这里创建的好处:清空冗余数据 151 // 一般地,在收到服务器传来的数据时接收的网络数据是二进制数据 152 self.data = [NSMutableData data];// 所以我们使用 NSMutableData 153 154 // 终止请求 155 // [self.connection cancel]; 156 } 157 158 // NSURLConnection 收到服务器传回的数据:可能会调用多次,因为每次只传递部分数据 159 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ 160 NSLog(@"---didReceiveData---"); 161 162 // 接受数据:将数据放进 self.data 中 163 [self.data appendData:data]; 164 } 165 166 // NSURLConnection 请求完成 167 - (void)connectionDidFinishLoading:(NSURLConnection *)connection{ 168 NSLog(@"---didFinishLoading---"); 169 170 // 若存在多个请求,判断处理即可 171 if (connection == self.connection) { 172 173 UIImage *aIamge = [UIImage imageWithData:self.data]; 174 UIImageView *imageView = (UIImageView *)[self.view viewWithTag:100]; 175 imageView.image = aIamge; 176 177 }else{ 178 179 // 捕获错误 180 NSError *error = nil; 181 NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:self.data options:0 error:&error]; 182 if (error) { 183 NSLog(@"error = %@",error); 184 } 185 NSLog(@"dic = %@",dic); 186 NSLog(@"length = %ld",self.data.length); 187 } 188 } 189 190 // NSURLConnection 请求失败 191 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ 192 193 NSLog(@"---didFailWithError---%@",error); 194 } 195 196 @end
注:如果使用了 http 协议进行网络请求,运行则会报 App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app‘s Info.plist file 的错误。这是因为在 iOS 9 中苹果将原 http 协议改成了 https 协议,使用 TLS1.2 SSL 加密请求数据。若要坚持使用 http 协议则需要在 Info.plist 文件中添加 App Transport SecuritySettings(Dictionary 型数据),并在 Dictionary 中添加 Allow Arbitray Loads(Bool 型数据,置 YES 即可)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律