当 UIKit > SwiftUI > UIKit 时不显示导航栏项目

Lew*_*s42 12 uinavigationbar uinavigationcontroller uibarbuttonitem swiftui

从 SwiftUI 视图推送到 UIKit 时,导航栏项目不存在或未添加。

\n

我在故事板中添加了一项,在代码中添加了一项,但都没有显示。

\n

这可能是 SwiftUI 中的一个错误,但我觉得这可能是一个很常见的情况,也许我遗漏了一些东西?

\n

与这个问题有一些重叠:Navigation Bar Items after Push from SwiftUI to UIKit尽管我不确定它们是否相同

\n

结果

\n

模拟器的GIF

\n

输入

\n

故事板

\n
    \n
  1. 没有代码,只有故事板
  2. \n
  3. 没有代码,只有故事板
  4. \n
  5. \n
\n
class MyHostingController: UIHostingController<SwiftUIView> {\n \n    required init?(coder aDecoder: NSCoder) {    \n        super.init(coder: aDecoder, rootView: SwiftUIView())\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
struct SwiftUIView: View {\n    var body: some View {\n        NavigationLink(\n            destination: MyUIKitView(),\n            label: {\n                Text("Go to MyUIKitView")\n            })\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

3和4之间粘上胶水

\n
struct MyUIKitView: UIViewControllerRepresentable {\n    typealias UIViewControllerType = MyUIKitViewController\n\n    func makeUIViewController(context: Context) -> MyUIKitViewController {\n        let sb = UIStoryboard(name: "Main", bundle: nil)\n        let myVC = sb.instantiateViewController(identifier: "MyUIKitViewController") as! MyUIKitViewController\n        return myVC\n    }\n    \n    func updateUIViewController(_ uiViewController: MyUIKitViewController, context: Context) {\n        print("\xe2\x99\xbb\xef\xb8\x8f")\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. \n
\n
class MyUIKitViewController: UIViewController {\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        //  ADD NAV BUTTON HERE  \n        navigationItem.rightBarButtonItems?.append(UIBarButtonItem(systemItem: .camera))\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 没有代码,只有故事板
  2. \n
\n

Raj*_*han 21

SwiftUI 视图使用自己的导航控制器,它忽略 UIKit 导航控制器,因此可能的解决方案是将导航栏设置为父控制器并通过编码设置导航栏元素。

像这样

class MyUIKitViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //  ADD NAV BUTTON HERE - must be in DispatchQueue
        DispatchQueue.main.async {
            self.parent?.navigationItem.title = "Your Title"
            self.parent?.navigationItem.rightBarButtonItems?.append(UIBarButtonItem(systemItem: .camera))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是使用self.navigationController?.navigationBar.topItem?. 这与上面完全相同。它给出了一个topItem。

class MyUIKitViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //  ADD NAV BUTTON HERE - must be in DispatchQueue
        DispatchQueue.main.async {
            self.navigationController?.navigationBar.topItem?.title = "Your Title"
            self.navigationController?.navigationBar.topItem?.rightBarButtonItems?.append(UIBarButtonItem(systemItem: .camera))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在启动视图时使用 DispatchQueue,此时父级尚未设置。(您也可以使用viewWillAppear代替DispatchQueue.main.async

编辑

如果您不想以编程方式添加元素并且需要使用故事板中的相同元素,那么您可以使用此方法。

class MyUIKitViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        //  ADD NAV BUTTON HERE
        navigationItem.rightBarButtonItems?.append(UIBarButtonItem(systemItem: .camera))
        
        DispatchQueue.main.async { //<--Here
            self.navigationController?.navigationBar.topItem?.title = self.navigationItem.title
            self.navigationController?.navigationBar.topItem?.rightBarButtonItems = self.navigationItem.rightBarButtonItems
        }
    }
}
Run Code Online (Sandbox Code Playgroud)