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

Swift同步问题:调用getMedicalData前idToken未被bearerToken设置

问题描述

我是Swift新手,bearerToken()函数用来更新getMedicalData()需要的idToken变量,但现在getMedicalData()会在bearerToken()完成idToken更新前就执行,导致它拿到的是空的idToken。怎么实现同步,让getMedicalData()等bearerToken()完全执行完再运行?

原调用代码

func login(username: String, password: String) {
    _ = Amplify.Auth.signIn(
        username: username,
        password: password
    ) { [weak self] result in
        switch result {
        case .success(let signInResult):
            print(SignInResult.self)
            if signInResult.isSignedIn {
                // 调用两个函数
                TokenManager.shared.bearerToken()
                getMedicalData()

                DispatchQueue.main.async {
                    self?.getCurrentAuthUser()
                }
            }
            
        case .failure(let error):
            print("Login error:", error)
        }
    }
}

原bearerToken()函数

func bearerToken() {
    _ = Amplify.Auth.fetchAuthSession { result in
        switch result {
        case .success(let session):
            if(session.isSignedIn) {
                if let sess = session as? AWSAuthCognitoSession {
                    let result = sess.getCognitoTokens()
                    switch result {
                    case .success(let tokens):
                        self.idToken = String(tokens.idToken)
                        self.refreshToken = tokens.refreshToken
                    case .failure(let error):
                        print("Fetch user tokens failed with error \(error)")
                    }
                }
            }
        case .failure(let error):
            print("Fetch session failed with error \(error)")
        }
    }
}
解决方案

方法1:给bearerToken()添加完成回调闭包

修改bearerToken(),让它在获取到token后触发传入的闭包,确保getMedicalData()在token更新完成后执行。

修改后的bearerToken():

func bearerToken(completion: @escaping () -> Void) {
    _ = Amplify.Auth.fetchAuthSession { result in
        switch result {
        case .success(let session):
            if(session.isSignedIn) {
                if let sess = session as? AWSAuthCognitoSession {
                    let result = sess.getCognitoTokens()
                    switch result {
                    case .success(let tokens):
                        self.idToken = String(tokens.idToken)
                        self.refreshToken = tokens.refreshToken
                        // 拿到token后执行回调
                        completion()
                    case .failure(let error):
                        print("Fetch user tokens failed with error \(error)")
                        completion()
                    }
                } else {
                    completion()
                }
            } else {
                completion()
            }
        case .failure(let error):
            print("Fetch session failed with error \(error)")
            completion()
        }
    }
}

修改login函数的调用逻辑:

func login(username: String, password: String) {
    _ = Amplify.Auth.signIn(
        username: username,
        password: password
    ) { [weak self] result in
        switch result {
        case .success(let signInResult):
            print(SignInResult.self)
            if signInResult.isSignedIn {
                // 等待token获取完成后再执行后续逻辑
                TokenManager.shared.bearerToken {
                    self?.getMedicalData()
                    
                    DispatchQueue.main.async {
                        self?.getCurrentAuthUser()
                    }
                }
            }
            
        case .failure(let error):
            print("Login error:", error)
        }
    }
}

方法2:使用Async/Await(Swift 5.5及以上版本)

这种写法更简洁易读,利用Swift的异步语法实现等待逻辑。

修改后的bearerToken()异步函数:

func bearerToken() async {
    do {
        let session = try await Amplify.Auth.fetchAuthSession()
        if session.isSignedIn, let sess = session as? AWSAuthCognitoSession {
            let tokens = try sess.getCognitoTokens().get()
            self.idToken = String(tokens.idToken)
            self.refreshToken = tokens.refreshToken
        }
    } catch {
        print("Fetch session or tokens failed with error \(error)")
    }
}

修改login函数的调用逻辑:

func login(username: String, password: String) {
    _ = Amplify.Auth.signIn(
        username: username,
        password: password
    ) { [weak self] result in
        switch result {
        case .success(let signInResult):
            print(SignInResult.self)
            if signInResult.isSignedIn {
                // 用Task包裹异步逻辑,等待token获取完成
                Task {
                    await TokenManager.shared.bearerToken()
                    self?.getMedicalData()
                    
                    DispatchQueue.main.async {
                        self?.getCurrentAuthUser()
                    }
                }
            }
            
        case .failure(let error):
            print("Login error:", error)
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 16:57:44