导航栏项目在UIKit > SwiftUI > UIKit时未显示

11

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

我已经在Storyboard中添加了一个项目和一个代码中的项目,但都没有显示出来。

这可能是SwiftUI中的一个bug,但我觉得这可能是一个相当常见的情况,也许我漏掉了什么?

这个问题与这个问题有些重叠:Navigation Bar Items after push from SwiftUI to UIKit,虽然我不确定它们是否相同。

结果

模拟器的Gif动画

输入

Storyboard

  1. 仅限Storyboard,无代码
  2. 仅限Storyboard,无代码
class MyHostingController: UIHostingController<SwiftUIView> {
 
    required init?(coder aDecoder: NSCoder) {    
        super.init(coder: aDecoder, rootView: SwiftUIView())
    }
}

struct SwiftUIView: View {
    var body: some View {
        NavigationLink(
            destination: MyUIKitView(),
            label: {
                Text("Go to MyUIKitView")
            })
    }
}

3号和4号之间的粘合剂

struct MyUIKitView: UIViewControllerRepresentable {
    typealias UIViewControllerType = MyUIKitViewController

    func makeUIViewController(context: Context) -> MyUIKitViewController {
        let sb = UIStoryboard(name: "Main", bundle: nil)
        let myVC = sb.instantiateViewController(identifier: "MyUIKitViewController") as! MyUIKitViewController
        return myVC
    }
    
    func updateUIViewController(_ uiViewController: MyUIKitViewController, context: Context) {
        print("♻️")
    }
}
class MyUIKitViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //  ADD NAV BUTTON HERE  
        navigationItem.rightBarButtonItems?.append(UIBarButtonItem(systemItem: .camera))
    }
}
  1. 无需编码,仅使用Storyboard
1个回答

18

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))
        }
    }
}

另一种解决方案是使用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))
        }
    }
}

当视图初始化时父级尚未设置,我使用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
        }
    }
}

1
这个可行,谢谢!我稍微编辑了一下你的答案,因为我没有注意到DispatchMain部分,所以我以为它不起作用。16小时后我会授予奖励! - lewis
这是我使用的代码:DispatchQueue.main.async { self.parent?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.addPhoto(_:))) } - lewis
谢谢!帮了大忙。我的UIKit视图未显示按钮,有时从UIKit->UIKit,有时从UIKit-SwiftUI-UIKit显示,因此还需要进行某些条件逻辑以检测先前视图的正确类型(UIViewController vs. UIHostingController)并使用相应的“navigationItem”。 - Mark Thormann
嗨,马克,你有一个UIKit-SwiftUI-UIKit的演示项目吗?我在导航栏方面遇到了困难...一旦我从UIKit>SwiftUI切换,导航项就会丢失。 - Bhuvan Bhatt
如何自定义导航标题颜色? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接