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

Swift中如何让NavigationLink等待异步请求完成后跳转?

解决方案:让NavigationLink等待异步操作完成

你的核心问题是roomGameName()函数里的异步回调还没执行完,函数就已经返回了初始空字符串,导致NavigationLink直接用空值跳转,根本等不到数据库返回的游戏名称。下面是具体的修正方案:

步骤1:用状态变量存储异步结果

在你的视图结构体里添加两个@State变量,分别存储游戏名称和导航触发状态:

@State private var fetchedGameName: String = ""
@State private var shouldNavigate = false

步骤2:重构异步获取逻辑

把原来的roomGameName()改成不返回值,而是拿到结果后更新状态并触发导航:

func fetchGameName() {
    getGameRoomName(roomCode: gameCode) { [weak self] roomName in
        guard let self = self else { return }
        if let name = roomName {
            self.fetchedGameName = name
            self.shouldNavigate = true // 拿到结果后才触发导航
        } else {
            print("Room name not found.")
        }
    }
}

步骤3:修改NavigationLink的触发方式

把按钮和NavigationLink分开,按钮负责触发异步请求,NavigationLink由状态变量控制是否跳转:

// 用户点击的按钮
Button("进入游戏") {
    fetchGameName()
}

// 受控的NavigationLink(隐藏在视图中)
NavigationLink(
    destination: destinationView(for: fetchedGameName, gameCode: gameCode, name: name),
    isActive: $shouldNavigate
) {
    EmptyView()
}

(可选)iOS16+推荐用NavigationStack

如果你的项目支持iOS16及以上,用NavigationStack的路径管理会更灵活:

  1. 先定义导航目标类型:
enum GameNavDestination: Hashable {
    case gameScreen(gameName: String, gameCode: String, userName: String)
}
  1. 在视图中添加路径状态:
@State private var navPath = NavigationPath()
  1. 修改异步函数直接添加路径:
func fetchGameName() {
    getGameRoomName(roomCode: gameCode) { [weak self] roomName in
        guard let self = self, let name = roomName else {
            print("Room name not found.")
            return
        }
        self.navPath.append(GameNavDestination.gameScreen(
            gameName: name,
            gameCode: self.gameCode,
            userName: self.name
        ))
    }
}
  1. 重构NavigationStack:
NavigationStack(path: $navPath) {
    Button("进入游戏") {
        fetchGameName()
    }
    .navigationDestination(for: GameNavDestination.self) { dest in
        switch dest {
        case .gameScreen(let gameName, let gameCode, let userName):
            destinationView(for: gameName, gameCode: gameCode, name: userName)
        }
    }
}

关键注意事项

  • 异步闭包里要用[weak self]避免循环引用,防止内存泄漏。
  • 如果数据库请求耗时较长,建议在按钮点击后显示加载动画(比如ProgressView),避免用户重复点击。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:42:18