1430 字
7 分钟
【iOS】网络请求与异步加载

目录

网络请求

为什么你的图片要异步加载?

​编辑

什么是“异步网络请求”

GET 与 POST

GET

POST

网络请求#

1,用NSString创建URL

2,创建NSURL对象:用URLSession对象进行网络请求

3,创建URLRequeset对其进行相关请求,分为GET和POST方法

4,根据会话创建任务

5,启动任务

图片

在与web服务器进行通信的过程中,这些类各自扮演了重要的角色。

NSURL对象负责以URL的格式保存web应用的位置。对大多数web服务,URL将包含基地址(base address)、web应用名和需要传送的参数。

NSURLRequest对象负责保存需要传送给web服务器的全部数据,这些数据包括:一个NSURL对象、缓存方案(caching policy)、等待web服务器响应的最长时间和需要通过HTTP协议传送的额外信息(NSMutableURLRequest 是** NSURLRequest** 的可变子类)。

每一个NSURLSessionTask对象都表示一个NSURLRequest 的生命周期。NSURLSessionTask可以跟踪NSURLRequest的状态,还可以对NSURLRequest执行取消、暂停和继续操作。NSURLSessionTask有多种不同功能 的子类,包括NSURLSessionDataTaskNSURLSessionUploadTask 和** NSURLSessionUDownloadTask** 。

NSURLSession对象可以看作是一个生产NSURLSessionTask对象的工厂。可以设置其生产出的NSURLSessionTask对象的通用属性,例如请求头的内容、是否允许在蜂窝网络下发送请求等。NSURLSession对象还有一个功能强大的委托,可以跟踪NSURLSessionTask对象的状态、处理服务器的认证要求等。

-(void) fetchData {
//1、创建URL
NSString *key = @"2db0265c1d084416b9275428252207";
NSString *urlString = [NSString stringWithFormat:@"https://api.weatherapi.com/v1/forecast.json?key=%@&q=%@&days=7&lang=zh&aqi=yes", key, self.cityName];
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//2、创建URL对象
NSURL *url = [NSURL URLWithString:urlString];
//3、创建URL Request,创建任务
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *weatherDic = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
self.weatherData = weatherDic; //最终数据落脚在weatherData
NSLog(@"%@",weatherDic);
dispatch_async(dispatch_get_main_queue(), ^{
/*
分别显示基本天气
每日天气
每小时天气
*/
[self setupWeatherData];
[self setupDailyForecastData];
[self setupHourlyForecastData];
});
}];
//启动任务
[task resume];
}

图片

为什么你的图片要异步加载?#

在仿写天气预报时,我们常常需要从网络加载天气图标,例如显示某个小时的天气状态图标。这看似简单的事情,如果处理不当,却很容易造成界面卡顿,甚至影响整个 App 的用户体验。

NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
self.weatherIcon.image = [UIImage imageWithData:data];

这段代码会直接在主线程中进行网络请求和图片解码:

  • 如果网络慢,用户界面会卡住。如果在滑动列表(比如 TableView)中这么做,滚动会非常不流畅

在 iOS 中,主线程负责所有界面渲染、用户交互。一旦主线程被“堵住”,就会引发体验崩溃。

而且在使用同步加载时:编译器会提示如下:

因此,我们需要异步网络请求。

什么是“异步网络请求”#

发起请求后不阻塞主线程(UI 线程),系统在线程池里做网络 I/O;等到有结果再通过回调/代理/await 把数据交回来。UI 始终流畅,你再把需要的 UI 更新切回主线程执行。

1,URLSession + completion handler(块回调)

最常用、简单。适合大多数 GET/POST、加载图片等。

2,URLSession + delegate(代理)

适合需要“边下边写文件/显示进度/断点续传”的下载或大文件上传。

3,URLSession + background session

App 退到后台仍能传输(系统托管),适合较大文件上传下载。

异步加载 + 主线程更新 UI

下面是一段优化后的代码:

- (void)loadWeatherIcon:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
self.weatherIcon.image = image;
});
}
}];
[task resume];
}

这段代码我们使用的是第一种:URLSession + completion handler 的 dataTask 异步请求。

解释:

        dataTask : 适合获取内存数据(图片,JSON)

        回调方式: completion handler block -> 请求完成后系统会在后台线程池调用

        配置:sharedSession 

  • dataTaskWithURL: 异步方法,不会阻塞主线程。默认就在系统分配的后台线程池中运行
  • dispatch_async(dispatch_get_main_queue(), ^{ … }) 是我们手动回到主线程更新 UI

使用异步请求后,会显著提升页面响应速度。

至于线程及其他本人暂时还未了解,以后再来填坑。

图片

GET 与 POST#

GET#

优点:3个全在一起(接口、链接、数据)可以在浏览器查看,书写简单。所有信息附加都在地址后面 缺点:明文,保密性差,通过GET提交数据,用户名和密码将明文出现在URL上。文件操作不方便

NSString *urlString = @"https://api.weatherapi.com/v1/current.json?key=xxx&q=beijing";
NSURL *url = [NSURL URLWithString:urlString];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@", json);
}
}];
[task resume];
#### POST
优点:密文,保密性好,文件类操作方便,后面不会出现?bjngh
缺点:无法在浏览器里面查看,实现复杂
POST把提交的数据则放置在是HTTP包的包体中,GET方式提交的数据最多只能是1024字节,理论上POST没有限制
因为post我还没详细了解,给出一段ai代码:
```objective-c
NSURL *url = [NSURL URLWithString:@"https://example.com/api/login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// 参数放在请求体
NSString *bodyString = @"username=wutong&password=123456";
request.HTTPBody = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
// 设置请求头
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"%@", json);
}
}];
[task resume];

因为本人的这个天气预报类似于一个小demo,所以使用GET,较为简便


原文发布于 CSDN:【iOS】网络请求与异步加载

【iOS】网络请求与异步加载
https://www.tommywutong.cn/posts/csdn-import/csdn-149614611-ios-/
作者
TommyWu
发布于
2025-09-01
许可协议
CC BY-NC-SA 4.0