iOS网络之异步加载
为什么你的图片要异步加载?
在仿写天气预报时,我们常常需要从网络加载天气图标,例如显示某个小时的天气状态图标。这看似简单的事情,如果处理不当,却很容易造成界面卡顿,甚至影响整个 App 的用户体验。
错误做法:图片同步加载会让 UI 卡顿
假设你在展示天气时这样加载图标:
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
self.weatherIcon.image = [UIImage imageWithData:data];
这段代码有什么问题?它会直接在主线程中进行网络请求和图片解码:
如果网络慢,用户界面会卡住甚至假死
如果在滑动列表(比如 TableView)中这么做,滚动会非常不流畅
图片越大,问题越明显
在 iOS 中,主线程负责所有界面渲染、用户交互。一旦主线程被你“堵住”,就会引发体验崩溃。
正确做法:异步加载 + 主线程更新 UI
为了保证用户界面流畅,我们应当把耗时操作放到后台线程去执行,只在主线程中更新 UI。下面是一段优化后的代码:
- (void)loadWeatherIcon:(NSString *)urlString {NSURL *url = [NSURL URLWithString:urlString];NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:urlcompletionHandler:^(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];
}
解释:
dataTaskWithURL: 默认就在系统分配的后台线程池中运行
dispatch_async(dispatch_get_main_queue(), ^{ ... }) 是我们手动回到主线程更新 UI
整个过程对用户而言是丝滑无感的异步体验