有没有一种在SwiftUI中实现
popToViewController(vc)
等效的方法?例如,如果我有以下流程:
View1 -> View2 -> View3 -> View4
考虑到我们无法控制导航栈,如何直接从View4弹回到View2?
popToViewController(vc)
等效的方法?例如,如果我有以下流程:
View1 -> View2 -> View3 -> View4
考虑到我们无法控制导航栈,如何直接从View4弹回到View2?
最近我在研究 SwiftUI 的一些功能时遇到了一个问题,即如何返回到特定的视图。经过一番研究之后,我找到了一个解决办法。你可以使用这个方法来返回到特定的视图。
首先,您需要为 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
}
}
}
}
}
使用以下代码获取 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
一旦您获得了 UINavigationController
实例,您可以使用以下代码轻松弹出到特定视图。
navigation.popViewControllers(viewsToPop: 2)
// 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
}
}
}
}
让它简单明了!!
为 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)
就是这样!