• 【iOS】简单的网络请求


    iOS小组要求,仿写知乎日报需要实现网络请求并解析JSON格式数据,这篇文章仅对基本的网络请求iOS中的JSON解析作以记录,还涉及到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]];
    
        //创建url
        NSURL* url = [NSURL URLWithString: urlString];
        
        //NSURLRequest* request = [NSURLRequest requestWithURL: url];
        
        //创建session
        NSURLSession* session = [NSURLSession sharedSession];
        
        //创建task
        NSURLSessionTask* 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];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    JSON解析

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

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

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

    请添加图片描述

    解析成对象我们仍旧看不懂,这里编码格式是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";
        
        //创建url
        NSURL* url = [NSURL URLWithString: urlString];
        
        //创建session
        NSURLSession* session = [NSURLSession sharedSession];
        
        //创建task
        NSURLSessionTask* 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);
            }
             // 停止自定义 Runloop
             CFRunLoopStop([runloop getCFRunLoop]);
        }];
    
        //任务启动,开始请求
        [task resume];
    
        // 运行自定义 Runloop
        [runloop run];
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    话题通讯自定义msg
    大数据到底是好是坏?_光点科技
    GPU-CUDA-图形渲染分析
    前后端分离——瑞吉外卖
    Kafka学习笔记之进阶篇
    docker 中安装 MySQL 以及使用
    Matlab论文插图绘制模板第62期—水平三维柱状图(Bar3h)
    若依3.6.0使用Mybatis-plus分页失效以及完美替换Pagehelper【已解决】
    【先楫HPM6750系列】RT-Thread SDIO驱动和文件系统
    05-jenkins与SonarQube代码审查集成
  • 原文地址:https://blog.csdn.net/XY_Mckevince/article/details/133953470