SwiftUI如何实现API请求成功后才跳转至新视图?
实现SwiftUI条件式导航:API成功获取有效数据后再跳转
当前代码里的NavigationLink会在点击时直接跳转,异步API调用的结果没法影响跳转时机。要实现仅在API调用成功且数据有效时才跳转,可以通过手动控制导航激活状态的方式解决,具体步骤如下:
1. 新增导航状态变量
在LoginView里添加一个@State变量,用来控制导航是否激活:
@State private var shouldNavigate = false
2. 拆分导航逻辑
把原来的NavigationLink拆成两部分:
- 一个普通按钮:负责触发API调用,等待结果并验证数据
- 一个隐藏的
NavigationLink:通过isActive绑定shouldNavigate,仅在状态为true时触发跳转
3. 调整ViewModel状态
在ViewModel里新增一个标记数据有效性的属性,方便View判断是否可以跳转:
class ViewModel: ObservableObject { @Published var isDataValid = false // 标记API返回数据是否有效 func fetchPlayerData() async { // 实际API请求逻辑 do { let response = try await yourAPICall() // 根据业务需求验证数据 self.isDataValid = self.validateResponse(response) } catch { self.isDataValid = false } } // 数据验证逻辑,根据实际需求实现 private func validateResponse(_ data: YourDataType) -> Bool { return data.requiredField != nil // 示例:检查关键字段是否存在 } }
4. 修改LoginView完整代码
import SwiftUI struct LoginView: View { @ObservedObject var vm: ViewModel @State private var username = "" @State private var shouldNavigate = false // 控制导航激活状态 // 修正原逻辑:原代码是用户名长度>2时禁用按钮,若逻辑反了可改成 return username.count > 2 private var searchAllowed: Bool { username.count <= 2 } var body: some View { NavigationView { VStack { Text("Enter your Username:") .font(.title.bold()) TextField("Username", text: $username) .frame(width: 280) .padding(.bottom) // 触发API调用的按钮 Button(action: { Task { await vm.fetchPlayerData() // 数据有效才触发跳转 if vm.isDataValid { shouldNavigate = true } } }) { ZStack { RoundedRectangle(cornerRadius: 5) .fill(.gray) .frame(width: 200, height: 50) Text("Search") .foregroundColor(.white) } } .disabled(searchAllowed) // 隐藏的导航链接,由shouldNavigate控制跳转 NavigationLink( destination: ProfileView(vm: vm), isActive: $shouldNavigate ) { EmptyView() } .hidden() } } } }
核心逻辑说明
- 点击按钮后先执行异步API调用,等待请求完成
- 根据ViewModel返回的
isDataValid状态,决定是否设置shouldNavigate = true - 隐藏的
NavigationLink会在shouldNavigate变为true时自动触发跳转,实现了条件式导航
内容的提问来源于stack exchange,提问作者Tom Miller
相关产品推荐
相关产品推荐

