iOS开发:WebService完成后执行Segue及AsyncTask等效方案问询
iOS中替代AsyncTask的异步方案及数据传递实现
嗨,作为iOS开发新手,我完全理解你想找类似Android AsyncTask的异步处理方案的需求~在iOS生态里并没有直接对应的AsyncTask,但有几种更贴合iOS开发习惯的异步处理方式,刚好能解决你网络请求完成后传递数据到下一个视图控制器的问题,我结合你的代码片段给你详细拆解:
1. 闭包(Closure)+ URLSession(最基础通用,兼容全iOS版本)
这是iOS开发中最常用的异步处理方式,核心是通过闭包回调获取异步请求的结果,再进行页面跳转和数据传递。
首先你需要改造FlightWebService的getFlightData方法,把它从同步逻辑改成带闭包回调的异步网络请求:
class FlightWebService { // 定义闭包回调,用Result类型统一处理成功/失败 func getFlightData(airportCode: String, minutesBefore: String, minutesAfter: String, completion: @escaping (Result<[Flight], Error>) -> Void) { // 替换成你的实际接口地址 guard let url = URL(string: "https://your-api-url.com/flights?airport=\(airportCode)&before=\(minutesBefore)&after=\(minutesAfter)") else { completion(.failure(NSError(domain: "InvalidURL", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求地址"]))) return } // 发起异步网络请求 let task = URLSession.shared.dataTask(with: url) { data, response, error in // 先处理请求错误 if let error = error { completion(.failure(error)) return } // 校验返回数据 guard let responseData = data else { completion(.failure(NSError(domain: "NoData", code: -2, userInfo: [NSLocalizedDescriptionKey: "未获取到数据"]))) return } // 解析JSON数据到你的Flight模型 do { let flights = try JSONDecoder().decode([Flight].self, from: responseData) completion(.success(flights)) } catch { completion(.failure(error)) } } task.resume() } }
然后在你的视图控制器中调用这个方法,拿到数据后跳转页面:
@IBAction func searchAction(_ sender: Any) { // 先校验输入合法性(避免强制解包崩溃) guard let airportName = airportCode.text, !airportName.isEmpty, let minutesBefore = minutesBehind.text, !minutesBefore.isEmpty, let minutesAfter = minutesAhead.text, !minutesAfter.isEmpty else { // 输入为空时弹提示 let alert = UIAlertController(title: "提示", message: "请填写完整信息", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } // 发起网络请求 FlightWebService().getFlightData(airportCode: airportName, minutesBefore: minutesBefore, minutesAfter: minutesAfter) { [weak self] result in // 网络请求在后台线程,必须切回主线程处理UI操作(跳转页面属于UI操作) DispatchQueue.main.async { switch result { case .success(let flights): // 跳转到下一个视图控制器并传递数据 let nextVC = FlightListViewController() // 替换成你的目标VC类名 nextVC.flightData = flights // 假设目标VC有接收数据的属性 self?.navigationController?.pushViewController(nextVC, animated: true) // 如果是模态跳转:self?.present(nextVC, animated: true) case .failure(let error): // 处理请求失败的情况 let alert = UIAlertController(title: "请求失败", message: error.localizedDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(alert, animated: true) } } } }
注意:用
[weak self]是为了避免循环引用,防止内存泄漏;所有UI操作必须在主线程执行,所以要用DispatchQueue.main.async切换线程。
2. Async/Await(iOS 15+,Swift 5.5+,代码更简洁)
如果你的项目支持iOS 15及以上版本,Async/Await是更优雅的选择,它让异步代码看起来像同步代码,可读性更强。
先改造FlightWebService的方法:
class FlightWebService { func getFlightData(airportCode: String, minutesBefore: String, minutesAfter: String) async throws -> [Flight] { guard let url = URL(string: "https://your-api-url.com/flights?airport=\(airportCode)&before=\(minutesBefore)&after=\(minutesAfter)") else { throw NSError(domain: "InvalidURL", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求地址"]) } // 用async/await发起请求 let (data, response) = try await URLSession.shared.data(from: url) // 校验HTTP响应状态 guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw NSError(domain: "InvalidResponse", code: -3, userInfo: [NSLocalizedDescriptionKey: "服务器响应异常"]) } // 解析数据 return try JSONDecoder().decode([Flight].self, from: data) } }
然后修改你的searchAction方法为异步方法:
@IBAction func searchAction(_ sender: Any) async { guard let airportName = airportCode.text, !airportName.isEmpty, let minutesBefore = minutesBehind.text, !minutesBefore.isEmpty, let minutesAfter = minutesAhead.text, !minutesAfter.isEmpty else { let alert = UIAlertController(title: "提示", message: "请填写完整信息", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } do { // 异步获取数据 let flights = try await FlightWebService().getFlightData(airportCode: airportName, minutesBefore: minutesBefore, minutesAfter: minutesAfter) // 跳转页面(保险起见切回主线程) DispatchQueue.main.async { let nextVC = FlightListViewController() nextVC.flightData = flights self.navigationController?.pushViewController(nextVC, animated: true) } } catch { // 处理错误 DispatchQueue.main.async { let alert = UIAlertController(title: "请求失败", message: error.localizedDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self.present(alert, animated: true) } } }
3. Combine框架(iOS 13+,响应式编程)
如果你需要处理复杂的数据流场景(比如多个异步请求联动、实时数据更新),Combine框架是个不错的选择,它属于响应式编程范畴。
先改造FlightWebService:
import Combine class FlightWebService { func getFlightData(airportCode: String, minutesBefore: String, minutesAfter: String) -> AnyPublisher<[Flight], Error> { guard let url = URL(string: "https://your-api-url.com/flights?airport=\(airportCode)&before=\(minutesBefore)&after=\(minutesAfter)") else { return Fail(error: NSError(domain: "InvalidURL", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的请求地址"])).eraseToAnyPublisher() } // 用Combine的dataTaskPublisher发起请求 return URLSession.shared.dataTaskPublisher(for: url) .map(\.data) // 提取返回的数据 .decode(type: [Flight].self, decoder: JSONDecoder()) // 解析数据 .eraseToAnyPublisher() // 隐藏内部实现细节 } }
然后在视图控制器中使用Combine:
import Combine class YourViewController: UIViewController { // 用来管理Combine订阅,防止内存泄漏 private var cancellables = Set<AnyCancellable>() @IBAction func searchAction(_ sender: Any) { guard let airportName = airportCode.text, !airportName.isEmpty, let minutesBefore = minutesBehind.text, !minutesBefore.isEmpty, let minutesAfter = minutesAhead.text, !minutesAfter.isEmpty else { let alert = UIAlertController(title: "提示", message: "请填写完整信息", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } FlightWebService().getFlightData(airportCode: airportName, minutesBefore: minutesBefore, minutesAfter: minutesAfter) .receive(on: DispatchQueue.main) // 切换到主线程处理结果 .sink( receiveCompletion: { [weak self] completion in if case .failure(let error) = completion { let alert = UIAlertController(title: "请求失败", message: error.localizedDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(alert, animated: true) } }, receiveValue: { [weak self] flights in let nextVC = FlightListViewController() nextVC.flightData = flights self?.navigationController?.pushViewController(nextVC, animated: true) } ) .store(in: &cancellables) // 保存订阅到cancellables中 } }
总结
- 如果你需要兼容低版本iOS(比如iOS 12及以下),优先选择闭包+URLSession的方案;
- 如果项目支持iOS 15+,Async/Await是最简洁易读的选择,推荐新手学习;
- 如果有复杂的数据流需求,再考虑Combine框架。
内容的提问来源于stack exchange,提问作者Ackman
相关产品推荐
相关产品推荐

