【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中调用次此方法

objectivec 复制代码
- (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];
}

JSON解析

请求下来的数据是NSData,二进制流

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

objectivec 复制代码
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,并在其中执行网络请求。这样,网络请求的回调就能够在正确的上下文中被执行,从而使打印输出能够正常显示

objectivec 复制代码
- (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];
}
相关推荐
得物技术7 小时前
得物 iOS 启动优化之 Building Closure
ios·性能优化
rainFFrain10 小时前
单例模式与线程安全
linux·运维·服务器·vscode·单例模式
goto_w15 小时前
uniapp上使用webview与浏览器交互,支持三端(android、iOS、harmonyos next)
android·vue.js·ios·uni-app·harmonyos
UpUpUp……1 天前
特殊类的设计/单例模式
开发语言·c++·笔记·单例模式
鸿蒙布道师1 天前
鸿蒙NEXT开发对象工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
刘小哈哈哈1 天前
封装了一个iOS多分区自适应宽度layout
macos·ios·cocoa
YJlio2 天前
TrollStore(巨魔商店)介绍及操作手册
macos·objective-c·cocoa
卡戎-caryon2 天前
【Linux网络与网络编程】03.UDP Socket编程
linux·服务器·网络·笔记·单例模式·udp·网络通信
布多2 天前
Tagged Pointer:苹果工程师的内存优化艺术
ios·源码
Rudon滨海渔村2 天前
新旧iPhone相册复制 - 相册图片视频对拷 - 换机 - 迁移设备数据 - 免费开源爱思助手
ios·iphone