UIViewControllerRepresentable:NavigationView 中忽略的导航标题和栏按钮项

jos*_*hap 10 uiviewcontroller uikit uinavigationitem navigationview swiftui

  • 我有一个UITableViewController包含在UIViewControllerRepresentable.
  • 我已经在我的视图控制器中设置了navigationItem.titlenavigationItem.leftBarButtonItems
  • 我提出我的UIViewControllerRepresentable实例作为SwiftUI的目的地NavigationLink一个SwiftUI内NavigationView
  • 当视图被推入导航堆栈时,表格视图出现,但标题和栏按钮项不出现。

这里发生了什么?

jos*_*hap 37

解决了!

问题和期望 SwiftUI 在底层使用 UINavigationController。因此,如果我使用 UIViewControllerRepresentable 将 UIViewController 推送到 SwiftUI NavigationView 上,那么我希望该视图控制器的导航项和工具栏项由所述导航控制器使用。正如我上面提到的,它们被忽略了。

根本原因 事实证明标题和项目被忽略,因为我的视图控制器的父级不是预期的 UINavigationController。相反,它的父级是一个由 SwiftUI 在幕后使用的中间包装视图控制器,它依次被推送到导航控制器上。它忽略了标题和项目,因为导航控制器正在向包装器询问其项目(没有),而不是我的视图控制器。

UIKit 解决方案 因此,如果您想从 UIKit 视图控制器设置标题或栏按钮项或工具栏项,那么您需要在其父项上设置它们:

self.parent?.navigationItem.title = “My Title”
Run Code Online (Sandbox Code Playgroud)

此外,您不能从 viewDidLoad 执行此操作,因为那时视图控制器似乎尚未被 SwiftUI 父级包装。您必须在 viewWillAppear 中执行此操作。

SwiftUI 解决方案 您还可以从 SwiftUI 设置标题和栏按钮。在您的 UIViewControllerRepresentable 实例上,只需像往常一样添加 .navigationBarTitle 和前导/尾随项目。然后你可以让按钮从你的 UIViewControllerRepresentable 实现中与你的视图控制器对话。

  • 能解决这个问题的你真是神啊。我一生都无法弄清楚为什么在 swiftUI 中使用视图控制器时我们的自定义导航项丢失了。 (2认同)
  • 对于那些感兴趣的人,我通过更新“UIViewControllerRepresentable”对象中的父导航项来使其工作,如下所示: ```func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { vc.parent?.navigationItem.title = vc.navigationItem.title vc.parent?.navigationItem.rightBarButtonItems = vc.navigationItem.rightBarButtonItems }``` (2认同)

pin*_*nch 21

这是一个 UIKit 解决方案,不需要对 UIViewController 进行内部更改,并且只应在包装器添加为父级时调用一次。

struct MyViewControllerRepresentable: UIViewControllerRepresentable {

    class Coordinator {
        var parentObserver: NSKeyValueObservation?
    }

    func makeUIViewController(context: Self.Context) -> MyViewController {
        let viewController =  MyViewController()
        context.coordinator.parentObserver = viewController.observe(\.parent, changeHandler: { vc, _ in
            vc.parent?.title = vc.title
            vc.parent?.navigationItem.rightBarButtonItems = vc.navigationItem.rightBarButtonItems
        })
        return viewController
    }

    func updateUIViewController(_ uiViewController: MyViewController, context: Self.Context) {}

    func makeCoordinator() -> Self.Coordinator { Coordinator() }
}
Run Code Online (Sandbox Code Playgroud)


f0r*_*0rz 5

josephap 的好建议但是他的 UIKit 解决方案使我的导航栏标题“闪烁”,不像通常显示的那样流畅。

我的解决方案只是从我的 SwiftUI 添加导航标题:

NavigationLink(destination: <YourUIViewControllerRepresentable>()
                                    .edgesIgnoringSafeArea([.top,.bottom])
                                    .navigationTitle(item.name)) {
                        Text(item.name)
                    }) 
Run Code Online (Sandbox Code Playgroud)