Swift 4.1异步调用Web API异常:首次点击失败二次成功的修复
修复Swift中Web API调用的异步顺序问题
这是个很典型的异步执行顺序问题,我来帮你分析并解决它:
问题根源
你遇到的核心问题是异步代码的执行时机:callMyApi()里的URLSession.dataTask(with:)是异步执行的网络请求——它会在后台线程发起请求,不会阻塞主线程。当你在按钮点击事件里调用callMyApi()后,立刻就去判断globalTempValue的值,这时候网络请求还没完成,globalTempValue还是初始的空字符串,所以第一次点击会输出fail 998。而第二次点击时,第一次的网络请求已经完成,globalTempValue被赋值成了999,所以会输出success 999。
你之前添加的DispatchQueue.main.async只是把赋值操作切回了主线程,但并没有改变"判断逻辑先于请求完成"的顺序,所以无法解决问题。
解决方案:使用闭包(Completion Handler)处理异步回调
最直接的修复方式是给callMyApi()添加一个完成回调闭包,让请求完成后再执行判断和后续逻辑。这样就能保证代码的执行顺序符合预期。
修改后的完整代码如下:
import UIKit class ViewController: UIViewController { @IBOutlet weak var lblDetail: UILabel! override func viewDidLoad() { super.viewDidLoad() } struct MyGitHub: Codable { let resultCode: String? private enum CodingKeys: String, CodingKey { case resultCode } } @IBAction func btnClickAction(_ sender: Any) { callMyApi { [weak self] resultCode in guard let self = self else { return } // 这里的逻辑会在网络请求完成后执行 if resultCode == "999" { print("success 999") // 还可以在这里更新UI,比如给lblDetail赋值 self.lblDetail.text = "请求成功" } else { print("fail 998") self.lblDetail.text = "请求失败" } } } func callMyApi(completion: @escaping (String?) -> Void) { guard let gitUrl = URL(string: "https://transsupp.com/tApp/ws01.ashx") else { completion(nil) return } URLSession.shared.dataTask(with: gitUrl) { data, response, error in guard let data = data, error == nil else { print("网络请求错误:\(error?.localizedDescription ?? "未知错误")") completion(nil) return } do { let decoder = JSONDecoder() let gitData = try decoder.decode(MyGitHub.self, from: data) // 把解析后的结果通过闭包传递出去 DispatchQueue.main.async { completion(gitData.resultCode) } } catch let err { print("解析数据错误:\(err)") completion(nil) } }.resume() } }
关键修改点说明
- 添加Completion Handler:给
callMyApi方法增加了completion: @escaping (String?) -> Void参数,用来在请求完成后传递结果。 - 调整执行顺序:按钮点击事件里,把原来的判断逻辑放到了
callMyApi的闭包回调中,这样逻辑会在网络请求完成并解析数据后才执行。 - 安全解包:去掉了强制解包
gitData.resultCode!,改用可选值传递,避免因接口返回null导致崩溃。 - 弱引用self:在闭包中使用
[weak self]避免循环引用,保证内存安全。
这样修改后,首次点击按钮时,网络请求完成后就会立刻执行判断逻辑,输出success 999,完全符合你的预期。
内容的提问来源于stack exchange,提问作者mannyCalavera
相关产品推荐
相关产品推荐

