如何从 UIKit 导航控制器中的 SwiftUI 视图获取 UIViewController

How to get a UIViewController from a SwiftUI View in a UIKit Navigation Controller

提问人:Gus 提问时间:11/18/2023 最后编辑:Gus 更新时间:11/18/2023 访问量:43

问:

在我的 SwiftUI/UIKit 项目中,我们使用 UIKit 的导航控制器进行导航。目前,我有一个从 SwiftUI 视图获取 UIViewController 的函数:

func popTo<T: View>(viewType: T.Type, animated: Bool) {
    if let viewController = rootNavigationController.viewControllers.first(where: {
        $0.self.description.contains(String(describing: viewType))
    }) {
        self.rootNavigationController.popToViewController(viewController, animated: animated)
    }
}

我想在不依赖字符串的情况下使它更加健壮。我想直接按类型过滤。下面是一个示例:

if let firstHostingController = rootNavigationController.viewControllers.first(where: { $0 is UIHostingController<MyView> }){
    self.popToView(viewController: firstHostingController, animated: true)
}

鉴于我们在 UIKit 导航控制器中工作,如何在不使用字符串进行类型比较的情况下修改我的 popTo 函数?

iOS SwiftUI UI导航控制器

评论

0赞 CouchDeveloper 11/19/2023
SwiftUI 提供了将导航声明为状态的工具。为什么不使用 SwiftUI 的原生工具进行声明式呢?
0赞 Gus 11/20/2023
鉴于我们在 UIKit 中实现的屏幕比 SwiftUI 多,因此在 SwiftUI 和 UIKit 屏幕之间无缝导航至关重要。你能提供一个样本来说明你指的是什么吗?

答:

0赞 Sweeper 11/18/2023 #1

您的第二个代码片段即将到来。只需替换为 type 参数即可。MyViewT

extension UINavigationController {
    func popTo<T: View>(viewType: T.Type, animated: Bool) {
        if let firstHostingController = viewControllers.first(where: { $0 is UIHostingController<T> }){
            self.popToViewController(firstHostingController, animated: true)
        }
    }
}

评论

0赞 Gus 11/21/2023
我以前试过,但没有用。当我将 UIHostingController<T> 替换为 UIHostingController<AnyView> 时,它返回了第一个 ViewController。
0赞 Sweeper 11/21/2023
@Gus 首先,“它返回了第一个ViewController”有什么问题?你期望它做什么?导航堆栈中甚至有哪些视图控制器?二、为什么要“代替”?为什么在这里使用?你想做什么?你错过了这么多细节,让我调试问题,甚至了解存在问题。UIHostingController<T>UIHostingController<AnyView>AnyView
0赞 Sweeper 11/21/2023
@Gus 请展示一个最小的可重现示例,说明什么不起作用。描述代码的预期行为和实际行为。请实际应用我的答案,不要用随机的东西替换你喜欢的任何东西。
0赞 Gus 11/21/2023
我提到 UIHostingController<AnyView> 的目的是提供其他信息,这些信息可能会激发对该问题的新见解。我将确保提供一个最小的可重现示例,并在不进行不必要的更改的情况下描述预期行为与实际行为。