UIViewControllerRepresentable:NavigationView 中忽略的导航标题和栏按钮项
UIViewControllerRepresentable: Navigation Title and Bar Button Items Ignored in NavigationView
- 我有一个
UITableViewController
子类,我已将其包装在 UIViewControllerRepresentable
. 中
- 我已经在我的视图控制器中设置了
navigationItem.title
和 navigationItem.leftBarButtonItems
。
- 我将我的
UIViewControllerRepresentable
实例作为 SwiftUI NavigationLink
在 SwiftUI NavigationView
中的目标。
- 当视图被推送到导航堆栈时,table 视图会出现,但标题和栏按钮项目不会出现。
这里发生了什么?
已解决!
问题与期望
SwiftUI 在底层使用 UINavigationController。因此,如果我使用 UIViewControllerRepresentable 将 UIViewController 推送到 SwiftUI NavigationView 上,那么我希望该导航控制器使用该视图控制器的导航项和工具栏项。正如我上面提到的,它们被忽略了。
根本原因
结果是标题和项目被忽略了,因为我的视图控制器的 parent 不是预期的 UINavigationController。相反,它 parent 是 SwiftUI 在后台使用的中间包装视图控制器,它又被推送到导航控制器上。它忽略了标题和项目,因为导航控制器正在向包装器询问其项目(具有 none),而不是我的视图控制器。
UIKit 解决方案
所以,如果你想从你的 UIKit 视图控制器设置标题或栏按钮项目或工具栏项目,那么你需要将它们设置在它的 parent 上,如下所示:
self.parent?.navigationItem.title = "My Title"
此外,您不能从 viewDidLoad 执行此操作,因为到那时视图控制器似乎还没有被 SwiftUI parent 包装。您必须在 viewWillAppear 中执行此操作。
SwiftUI 解决方案
您还可以从 SwiftUI 设置标题和栏按钮。在您的 UIViewControllerRepresentable 实例上,只需像往常一样添加 .navigationBarTitle 和 leading/trailing 项目。然后你可以让按钮从你的 UIViewControllerRepresentable 实现中与你的视图控制器对话。
来自 josephap 的好建议但是他的 UIKit 解决方案使我的导航栏标题 'flicker' 不像通常显示的那样流畅。
我的解决方案是从我的 SwiftUI 添加导航标题:
NavigationLink(destination: <YourUIViewControllerRepresentable>()
.edgesIgnoringSafeArea([.top,.bottom])
.navigationTitle(item.name)) {
Text(item.name)
})
这是一个 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() }
}
- 我有一个
UITableViewController
子类,我已将其包装在UIViewControllerRepresentable
. 中
- 我已经在我的视图控制器中设置了
navigationItem.title
和navigationItem.leftBarButtonItems
。 - 我将我的
UIViewControllerRepresentable
实例作为 SwiftUINavigationLink
在 SwiftUINavigationView
中的目标。 - 当视图被推送到导航堆栈时,table 视图会出现,但标题和栏按钮项目不会出现。
这里发生了什么?
已解决!
问题与期望 SwiftUI 在底层使用 UINavigationController。因此,如果我使用 UIViewControllerRepresentable 将 UIViewController 推送到 SwiftUI NavigationView 上,那么我希望该导航控制器使用该视图控制器的导航项和工具栏项。正如我上面提到的,它们被忽略了。
根本原因 结果是标题和项目被忽略了,因为我的视图控制器的 parent 不是预期的 UINavigationController。相反,它 parent 是 SwiftUI 在后台使用的中间包装视图控制器,它又被推送到导航控制器上。它忽略了标题和项目,因为导航控制器正在向包装器询问其项目(具有 none),而不是我的视图控制器。
UIKit 解决方案 所以,如果你想从你的 UIKit 视图控制器设置标题或栏按钮项目或工具栏项目,那么你需要将它们设置在它的 parent 上,如下所示:
self.parent?.navigationItem.title = "My Title"
此外,您不能从 viewDidLoad 执行此操作,因为到那时视图控制器似乎还没有被 SwiftUI parent 包装。您必须在 viewWillAppear 中执行此操作。
SwiftUI 解决方案 您还可以从 SwiftUI 设置标题和栏按钮。在您的 UIViewControllerRepresentable 实例上,只需像往常一样添加 .navigationBarTitle 和 leading/trailing 项目。然后你可以让按钮从你的 UIViewControllerRepresentable 实现中与你的视图控制器对话。
来自 josephap 的好建议但是他的 UIKit 解决方案使我的导航栏标题 'flicker' 不像通常显示的那样流畅。
我的解决方案是从我的 SwiftUI 添加导航标题:
NavigationLink(destination: <YourUIViewControllerRepresentable>()
.edgesIgnoringSafeArea([.top,.bottom])
.navigationTitle(item.name)) {
Text(item.name)
})
这是一个 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() }
}