SwiftUI - 如何在SwiftUI中返回到特定的视图?

3
有没有一种在SwiftUI中实现popToViewController(vc)等效的方法?例如,如果我有以下流程:

View1 -> View2 -> View3 -> View4

考虑到我们无法控制导航栈,如何直接从View4弹回到View2?


1
popTo和popToRoot现在不可用。您可以参考https://dev59.com/21MH5IYBdhLWcg3w_Wd_#57513566并找到一些解决方法。 - Alfred Woo
也许 @Enviroment 变量可以帮助。 - Mojtaba Hosseini
看一下这个问题 https://dev59.com/AbXna4cB1Zd3GeqPT_9o 我为SwiftUI创建了一个开源的导航栈 (https://github.com/biobeats/swiftui-navigation-stack),你可以使用它来弹出到特定的视图。 - superpuccio
3个回答

0

最近我在研究 SwiftUI 的一些功能时遇到了一个问题,即如何返回到特定的视图。经过一番研究之后,我找到了一个解决办法。你可以使用这个方法来返回到特定的视图。

  1. 首先,您需要为 UINavigationController 创建一个扩展。请查看下面提到的代码。

    import UIKit
    
    extension UINavigationController {
    
        func popToViewController(ofClass: AnyClass, animated: Bool = true) {
            if let vc = viewControllers.filter({$0.isKind(of: ofClass)}).last {
                popToViewController(vc, animated: animated)
            }
        }
    
        func popViewControllers(viewsToPop: Int, animated: Bool = true) {
            if viewControllers.count > viewsToPop {
                let vc = viewControllers[viewControllers.count - viewsToPop - 1]
                popToViewController(vc, animated: animated)
            }
        }
    
        func popBack<T: UIViewController>(toControllerType: T.Type) {
            if var viewControllers: [UIViewController] = self.navigationController?.viewControllers {
                viewControllers = viewControllers.reversed()
                for currentViewController in viewControllers {
                    if currentViewController .isKind(of: toControllerType) {
                        self.navigationController?.popToViewController(currentViewController, animated: true)
                        break
                    }
                }
            }
        }
    }
    
  2. 使用以下代码获取 UINavigationController 实例。

    let window = UIApplication.shared.connectedScenes
        .filter { $0.activationState == .foregroundActive }
        .map { $0 as? UIWindowScene }
        .compactMap { $0 }
        .first?.windows
        .filter { $0.isKeyWindow }
        .first
    let navigation = window?.rootViewController?.children.first as? UINavigationController
    
  3. 一旦您获得了 UINavigationController 实例,您可以使用以下代码轻松弹出到特定视图。

    navigation.popViewControllers(viewsToPop: 2)
    

0
// Do not change, it must be same with NavigationBarTitle
enum ViewIdentifiers: String {
    case homeView = "Home"
    case detailView = "Detail Page"
}    

struct HomeView: View {

 var body: some View {
   VStack {
      NavigationLink {
          DetailView()
      } label: {
         Text("Go To Detail")
     }
   }
   .navigationBarTitle(ViewIdentifiers.homeView.rawValue, displayMode: .inline)
 }
}


struct DetailView: View {

 var body: some View {
   VStack {
       Text("Detail")
         .onTapGesture { UIApplication.shared.popToView(ViewIdentifiers.homeView) }
   }
   .navigationBarTitle("Detail Page", displayMode: .inline)
 }
}

extension UIApplication {

  var keyWindow: UIWindow? {
    return UIApplication.shared.connectedScenes
        .filter { $0.activationState == .foregroundActive }
        .first(where: { $0 is UIWindowScene })
        .flatMap({ $0 as? UIWindowScene })?.windows
        .first(where: \.isKeyWindow)
  }
 

 func getNavigationController() -> UINavigationController? {
    guard let window = keyWindow else { return nil }
    guard let rootViewController = window.rootViewController else { return nil }
    guard let navigationController = findNavigationController(viewController: rootViewController) else { return nil }
    return navigationController
  }
  
  private func findNavigationController(viewController: UIViewController?) -> UINavigationController? {
    guard let viewController = viewController else {
        return nil
    }
    
    if let navigationController = viewController as? UINavigationController {
        return navigationController
    }
    
    for childViewController in viewController.children {
        return findNavigationController(viewController: childViewController)
    }
    
    return nil
 }

 func popToView(_ identifier: ViewIdentifiers) {
    guard let navigationController = getNavigationController() else {
        return
    }
    
    for vc in navigationController.children {
        if vc.navigationItem.title == identifier.rawValue {
            navigationController.popToViewController(vc, animated: true)
            break
        }
    }
  }

}

0

让它简单明了!!

UINavigationController 添加一个扩展。

extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
  if let vc = viewControllers.last(where: { $0.isKind(of: ofClass) }) {
    popToViewController(vc, animated: animated)
  }
}

添加以下代码以进入特定的SwiftUI视图。您必须将SampleView位置提及到您的视图中。

navigationController.popToViewController(ofClass: HostingController<SampleView>.self)

就是这样!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接