SwiftUI中实现Text长按手势跳转至另一界面的问题
解决方案
因为你的场景是在UIKit导航栈中嵌入SwiftUI页面,有两种可行的实现方式:
方式一:SwiftUI原生导航(推荐)
利用SwiftUI的NavigationStack和状态变量控制导航链接,这种方式能和UIKit的导航栈无缝协同:
- 修正
ClassB的命名(Swift规范要求类型首字母大写):
struct ClassB: View { var body: some View { VStack(alignment: .leading){ Text("Hello") } .navigationTitle("Class B") } }
- 修改
ClassA的代码,添加状态变量和导航逻辑:
struct ClassA: View { // 控制导航触发的状态变量 @State private var shouldNavigateToClassB = false var body: some View { NavigationStack { VStack(alignment: .leading, spacing: 7) { Text("user 1") Text("Long Press Here") .onLongPressGesture(minimumDuration: 2) { // 触发导航跳转 shouldNavigateToClassB = true } Text("User 2") } .navigationTitle("Class A") // 绑定状态的导航目标 .navigationDestination(isPresented: $shouldNavigateToClassB) { ClassB() } } } }
方式二:直接调用UIKit导航控制器
如果更习惯UIKit的导航逻辑,可以直接获取当前顶层导航控制器并push新的SwiftUI页面:
- 添加一个获取顶层导航控制器的扩展(可放在任意Swift文件中):
extension UIApplication { func topNavigationController() -> UINavigationController? { let keyWindow = connectedScenes .filter({$0.activationState == .foregroundActive}) .compactMap({$0 as? UIWindowScene}) .first?.windows .first(where: {$0.isKeyWindow}) guard let rootVC = keyWindow?.rootViewController else { return nil } return findTopNavigationController(from: rootVC) } private func findTopNavigationController(from viewController: UIViewController) -> UINavigationController? { if let navVC = viewController as? UINavigationController { return navVC } for childVC in viewController.children { return findTopNavigationController(from: childVC) } return viewController.presentedViewController.flatMap { findTopNavigationController(from: $0) } } }
- 修改
ClassA的长按手势处理代码:
struct ClassA: View { var body: some View { VStack(alignment: .leading, spacing: 7) { Text("user 1") Text("Long Press Here") .onLongPressGesture(minimumDuration: 2) { // 创建ClassB的托管控制器 let classBView = ClassB() let hostingController = UIHostingController(rootView: classBView) // 获取顶层导航控制器并执行push UIApplication.shared.topNavigationController()?.pushViewController(hostingController, animated: true) } Text("User 2") } .navigationTitle("Class A") } }
注意:请务必将原代码中的
classB改为ClassB,符合Swift类型首字母大写的命名规范。
内容的提问来源于stack exchange,提问作者King
相关产品推荐
相关产品推荐

