【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];
}
相关推荐
float_六七1 小时前
Java——单例类设计模式
java·单例模式·设计模式
桃子是唯一的水果2 小时前
java 单例模式(Lazy Initialization)实现遍历文件夹下所有excel文件且返回其运行时间
java·单例模式·maven
OKXLIN9 小时前
IOS UITextField 无法隐藏键盘问题
ios·objective-c
AL.千灯学长17 小时前
DeepSeek接入Siri(已升级支持苹果手表)完整版硅基流动DeepSeek-R1部署
人工智能·gpt·ios·ai·苹果vision pro
菜鸟一枚在这1 天前
深入解析设计模式之单例模式
开发语言·javascript·单例模式
FLZJ_KL1 天前
【设计模式】【创建型模式】单例模式(Singleton)
java·单例模式·设计模式
非 白1 天前
【Java】单例模式
java·笔记·单例模式
openinstall全渠道统计2 天前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
早起的年轻人2 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
貂蝉空大2 天前
uni-app开发安卓和ios app 真机调试
android·ios·uni-app