You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Swift API调用中Firebase getIDToken返回nil的问题

问题根因
  • 当前实现的token()函数是典型的“异步操作同步取值”错误实现:getIDToken的完成回调是异步调度执行的,你在发起Token请求后立刻执行return result,这个时机回调还没有被触发,result永远是初始的nil值。
  • 额外存在两个实现问题:
    • 对Auth.auth().currentUser做了强制解包,用户未登录时会直接触发崩溃
    • Token获取成功的分支错误打印了err,属于代码笔误,成功场景下err本身就是nil
代码修改方案

1. 重构SessionData的Token获取方法

彻底废弃同步返回的写法,改为通过完成回调传递Token获取结果,同时增加登录状态、Token为空的容错判断:

class SessionData : ObservableObject {
    // 原同步token()方法替换为带错误处理的异步回调方法
    func getIDToken(completion: @escaping (Result<String, Error>) -> Void) {
        // 先校验当前登录态,避免强制解包崩溃
        guard let currentUser = Auth.auth().currentUser else {
            completion(.failure(NSError(
                domain: "AuthError",
                code: -1,
                userInfo: [NSLocalizedDescriptionKey: "当前账号未登录"]
            )))
            return
        }
        currentUser.getIDToken { (token, error) in
            if let error = error {
                print("*** TOKEN获取失败: \(error.localizedDescription)")
                completion(.failure(error))
                return
            }
            guard let validToken = token else {
                completion(.failure(NSError(
                    domain: "AuthError",
                    code: -2,
                    userInfo: [NSLocalizedDescriptionKey: "获取到的Token为空"]
                )))
                return
            }
            print("*** TOKEN获取成功")
            completion(.success(validToken))
        }
    }
}

2. 调整FetchPosts的加载逻辑

把原来直接拼URL的步骤,挪到Token获取成功的回调内部执行,保证异步流程的先后顺序正确:

func load(api: Bool, session: SessionData) {
    if api {
        // 先异步获取Token,拿到合法Token后再发起网络请求
        session.getIDToken { [weak self] result in
            guard let self = self else { return }
            switch result {
            case .success(let token):
                // Token校验通过后再拼接接口地址
                guard let url = URL(string: MyAPI.getAddress(token: token)) else {
                    DispatchQueue.main.async {
                        session.json_error(error: "接口地址格式非法")
                    }
                    return
                }
                // 原有的网络请求逻辑保持不变
                URLSession.shared.dataTask(with: url) {(data, response, error) in
                    do {
                        if let postsData = data {
                            let decodedData = try JSONDecoder().decode(Response.self, from: postsData)
                            DispatchQueue.main.async {
                                self.posts = decodedData.result
                                if decodedData.error != nil {
                                    print("ERROR: \(decodedData.error!)")
                                    session.json_error(error: decodedData.error!)
                                }
                            }
                        } else {
                            print("No data. Connection error.")
                            DispatchQueue.main.async {
                                session.json_error(error: "Could not connect to server, please try again!")
                            }
                        }
                    } catch {
                        print("* Error: \(error)")
                    }
                }.resume()
            case .failure(let error):
                // Token获取失败时直接触发错误提示
                DispatchQueue.main.async {
                    session.json_error(error: "身份校验失败,请重新登录:\(error.localizedDescription)")
                }
            }
        }
    } else {
        // 原有的本地测试JSON加载逻辑无需修改
        let url = Bundle.main.url(forResource: "test", withExtension: "json")!
        let data = try! Data(contentsOf: url)
        let decoder = JSONDecoder()
        if let products = try? decoder.decode([Post].self, from: data) {
            self.posts = products
        }
    }
}
落地注意事项
  • 不要尝试用信号量、锁之类的方式把异步Token获取强行改成同步等待,这类写法会阻塞当前线程,一旦在主线程调用就会造成界面卡死
  • 所有涉及更新@Published发布属性、调用错误提示的逻辑,必须切回主线程执行,避免触发UI更新的线程警告
  • 原调用posts.load(...)的位置不需要做任何修改,整个流程的异步嵌套对上层是完全透明的

内容的提问来源于stack exchange,提问作者Max

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.26 09:27:04