当前位置: 首页 > news >正文

【iOS】简单的网络请求

应iOS小组要求,仿写知乎日报需要实现网络请求并解析JSON格式数据,这篇文章仅对基本的网络请求iOS中的JSON解析作以记录,还涉及到RunLoop的一点小插曲,具体请求过程和原理以后会详细学习!🙏

    • 基本网络流程
    • 简单的网络请求示例
    • JSON解析
    • 网络请求图示
    • JSON格式也可以通过第三方库JSONModel直接在程序中解析,后续将加以学习🫡
    • 网络请求其实可通过第三方库AFNetworking来进行,为我们简化了许多流程,后续将加以学习🤟🏻
    • 有关RunLoop的小插曲


基本网络流程

  • NSURL(Uniform Resource Locator)

URL可直接理解为请求网址,如:https://v0.yiketianqi.com/api?unescape=1&version=v9&appid=72961936&appsecret=m78Z0m2T&city=北京&unescape=1

其格式为:[协议类型]://[服务器器地址]:[端⼝口号]/[资源层级UNIX⽂文件路路径][⽂文件名]?[查询]#[⽚片段ID]

方法URLWithString:将要请求的地址字符串包装成NSURL对象:
请添加图片描述

  • NSURLRequest

NSURLRequest对象就代表一个请求
请添加图片描述
会将NSURL对象以及各种参数设置封装起来,无需设置其他参数时方法+ (instancetype)requestWithURL:(NSURL *)URL;即可

  • NSURLSession

一个session可创建多个请求request,并负责接收、发送和处理请求
整个程序中也可以有多个session

创建session方法(单例sharedSession):
请添加图片描述

session会将request封装成Task:
请添加图片描述
来处理数据

可以看到,如果请求逻辑没那么复杂,也可直接用第二个方法将NSURL封装成session

    • NSURLSessionTask
      请添加图片描述
      用Task类的resume方法来开启请求

简单的网络请求示例

用一个方法dataLoader封装一下,最后在Controller中调用次此方法

- (void)dataLoader {self.dict = [[NSDictionary alloc] init];NSString* urlString = @"https://v0.yiketianqi.com/api?unescape=1&version=v9&appid=72961936&appsecret=m78Z0m2T&city=北京&unescape=1";//处理字符//urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters: [NSCharacterSet URLQueryAllowedCharacterSet]];//创建urlNSURL* url = [NSURL URLWithString: urlString];//NSURLRequest* request = [NSURLRequest requestWithURL: url];//创建sessionNSURLSession* session = [NSURLSession sharedSession];//创建taskNSURLSessionTask* task = [session dataTaskWithURL: url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (!error) {//解析数据//self.dict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &error];NSLog(@"%@", data);} else {NSLog(@"请求出现错误:%@", error);}}];//任务启动,开始请求[task resume];
}

JSON解析

请求下来的数据是NSData,二进制流
请添加图片描述

下面用一个类NSJSONSerialization将该数据转换成对象,用字典接收并打印出来:

self.dict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &error];
NSLog(@"%@", self.dict);

请添加图片描述

解析成对象我们仍旧看不懂,这里编码格式是Unicode转义序列这就需要JSON解析(Unicode转中文, … , …),网上有许多JSON解析在线工具

在这里插入图片描述

网络请求图示

下面用一张图展示网络请求流程:

在这里插入图片描述


JSON格式也可以通过第三方库JSONModel直接在程序中解析,后续将加以学习🫡

网络请求其实可通过第三方库AFNetworking来进行,为我们简化了许多流程,后续将加以学习🤟🏻

有关RunLoop的小插曲

编者一开始其实是在main函数里调用并执行请求的,最后发现command Line Tool并没有显示打印内容,咨询了zxb10学长发现原来是RunLoop的问题

RunLoop 是一个事件循环,负责处理各种事件,包括网络请求的回调。在进行异步网络请求时,通常会使用回调函数或代理方法来处理请求的响应。这些回调函数或代理方法需要在 Run Loop 中执行,才能正确地接收和处理网络请求的响应

  • main函数中,默认情况下并没有启动RunLoop,因此当网络请求的回调发生时,由于Runloop没有运行,无法处理这些事件,包括打印输出
  • 而在iOS项目中,主线程的RunLoop默认会启动,并且在主RunLoop运行期间,ta会一直处于运行状态,直到应用程序退出。这意味着主线程的RunLoop会不断地处理事件,包括网络请求的回调和其他消息

为了解决这个问题,可以在main函数中创建一个自定义的RunLoop,并在其中执行网络请求。这样,网络请求的回调就能够在正确的上下文中被执行,从而使打印输出能够正常显示

- (void)dataLoader {// 创建一个自定义 Runloop,并运行在主线程上NSRunLoop *runloop = [NSRunLoop mainRunLoop];self.dict = [[NSDictionary alloc] init];NSString* urlString = @"https://v0.yiketianqi.com/api?unescape=1&version=v9&appid=72961936&appsecret=m78Z0m2T&city=北京&unescape=1";//创建urlNSURL* url = [NSURL URLWithString: urlString];//创建sessionNSURLSession* session = [NSURLSession sharedSession];//创建taskNSURLSessionTask* task = [session dataTaskWithURL: url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {if (!error) {//解析数据self.dict = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &error];NSLog(@"%@", self.dict);} else {NSLog(@"请求出现错误:%@", error);}// 停止自定义 RunloopCFRunLoopStop([runloop getCFRunLoop]);}];//任务启动,开始请求[task resume];// 运行自定义 Runloop[runloop run];
}
http://www.lryc.cn/news/204831.html

相关文章:

  • Vulnhub系列靶机---mhz_cxf: c1f
  • SDRAM与DRAM
  • 数据库基础(一)【MySQL】
  • C++ -- 位运算与常用库函数(ACWING语法基础)
  • 老卫带你学---leetcode刷题(557. 反转字符串中的单词 III)
  • IEEE754 标准存储浮点数
  • CSS 两栏布局
  • RHCSA常用命令总结
  • 【Spring Boot】详解restful api
  • LISTAGG 函数
  • 485modbus转profinet网关连三菱变频器modbus通讯配置案例
  • 1024节日
  • 【@EnableWebMvc的原理】
  • css3 2d转换transform详细解析与代码实例transform
  • 点亮现代编程语言的男人——C语言/UNIX之父Dennis Ritchie
  • 找不到msvcp100.dll解决教程
  • 萃取和constexpr
  • 决策树完成图片分类任务
  • Docker 容器全部停止命令
  • 对GRUB和initramfs的小探究
  • springboo单机多线程高并发防止重复消费的redis方案
  • Java架构师内功数据库
  • 踩着节日的小尾巴
  • UG\NX二次开发 设置视图中心 UF_VIEW_set_center
  • leetcode做题笔记201. 数字范围按位与
  • 游戏盾如何有效防护DDoS
  • JavaScript中的类型转换
  • 01-JVM 内存结构
  • 树与二叉树(考研版)
  • 前端车牌键盘组件