如何在API响应返回后,实现按钮点击跳转新视图?
解决API响应后跳转新视图的SwiftUI实现
先修正你代码里的一个小问题:onSubmit方法里的参数fieldTitle应该改为title,对应你定义的@State变量。下面提供几种常用的跳转实现方案,适配不同iOS版本和场景:
方案一:使用NavigationStack(iOS 16+)
这是iOS16及以上的推荐导航方式,通过NavigationPath管理导航栈:
struct FormView: View { @StateObject private var vm = MyViewModel(myService: MyService()) @State private var title: String = "" @State private var navigationPath = NavigationPath() var body: some View { NavigationStack(path: $navigationPath) { VStack { TextField( "Type something", text: $title ) .textFieldStyle(.roundedBorder) Button(action: onSubmit) { Text("Submit") .padding() .background(.blue) .foregroundColor(.white) .cornerRadius(8) } } .padding() // 定义导航目标视图 .navigationDestination(for: Post.self) { post in DetailView(post: post) // 替换成你的目标视图 } .onChange(of: vm.post) { _, newPost in if let post = newPost { navigationPath.append(post) // 跳转后清空vm.post,避免重复触发跳转 vm.post = nil } } } } func onSubmit() { vm.submit(title: title) } } // 示例模型和目标视图 struct Post: Identifiable { let id = UUID() let title: String } struct DetailView: View { let post: Post var body: some View { Text("Post Content: \(post.title)") .navigationTitle("Detail") } }
方案二:使用NavigationView(iOS 13-15)
如果需要兼容旧版本iOS,用隐藏的NavigationLink配合状态变量控制:
struct FormView: View { @StateObject private var vm = MyViewModel(myService: MyService()) @State private var title: String = "" @State private var shouldNavigate = false var body: some View { NavigationView { VStack { TextField( "Type something", text: $title ) .textFieldStyle(.roundedBorder) Button(action: onSubmit) { Text("Submit") .padding() .background(.blue) .foregroundColor(.white) .cornerRadius(8) } // 隐藏的导航链接,通过状态控制激活 .background( NavigationLink( destination: DetailView(post: vm.post!), isActive: $shouldNavigate, label: { EmptyView() } ) ) } .padding() .onChange(of: vm.post) { _, newPost in shouldNavigate = newPost != nil // 跳转后重置状态,避免重复触发 if shouldNavigate { DispatchQueue.main.async { vm.post = nil } } } } } func onSubmit() { vm.submit(title: title) } }
方案三:使用Sheet弹出视图
如果需要以弹出层形式展示新视图,用sheet实现:
struct FormView: View { @StateObject private var vm = MyViewModel(myService: MyService()) @State private var title: String = "" @State private var showDetailSheet = false var body: some View { VStack { TextField( "Type something", text: $title ) .textFieldStyle(.roundedBorder) Button(action: onSubmit) { Text("Submit") .padding() .background(.blue) .foregroundColor(.white) .cornerRadius(8) } .sheet(isPresented: $showDetailSheet) { if let post = vm.post { DetailView(post: post) } } .onChange(of: vm.post) { _, newPost in showDetailSheet = newPost != nil // 弹出后重置状态 if showDetailSheet { DispatchQueue.main.async { vm.post = nil } } } } .padding() } func onSubmit() { vm.submit(title: title) } }
关键注意事项
- 确保你的
MyViewModel中post属性是@Published的,否则onChange不会触发:class MyViewModel: ObservableObject { @Published var post: Post? private let myService: MyService init(myService: MyService) { self.myService = myService } func submit(title: String) { // API调用示例,确保在主线程更新post myService.createPost(title: title) { [weak self] post in DispatchQueue.main.async { self?.post = post } } } } - 跳转后清空
vm.post是为了避免用户返回当前页面后,旧的post值再次触发跳转逻辑。
内容的提问来源于stack exchange,提问作者user2343632
相关产品推荐
相关产品推荐

