I'm new to swiftUI. We have both UIKit and swiftUI code in our project and we have some custom logic to add few UIBarButtonItem. I need to pass viewController.navigationItem.rightBarButtonItems array from UIKit code to a separate swiftUI module and then create toolBar with these rightBarButtonItems.
struct ToolBarItems: ToolbarContent {
let barButtons: [UIBarButtonItem]
init(barButtons: [UIBarButtonItem]) {
self.barButtons = barButtons
}
var body: some ToolbarContent {
ToolbarItem(placement: .principal) {
Text("principal Title")
}
}
@ToolbarContentBuilder
var toolbarButtons: some ToolbarContent {
ForEach(barButtons) { item in
ToolbarItem(placement: .navigationBarTrailing) {
Button(item.title!) {
}
}
}
}
}
This gives errors "No exact matches in reference to static method 'buildExpression'". Not sure how to do this conversion. Please advise.
The error is because
ForEachis notToolbarContent. You can create aToolbarItemGroupinstead, which takes a@ViewBuilder, and you can put theForEachin the@ViewBuilder:Also, you would need
extension UIBarButtonItem: Identifiable {}for theForEachto work.However,
item.titleis main actor-isolated, butToolbarContent.bodyis not. While you can isolateToolbarContent.bodyto@MainActor, you would end up implementing a non-isolated protocol requirement with an actor-isolated property, which is potentially not safe.I would create my own struct to represent a "navigation bar item". For example, if you are only interested in the title, image, and action of the
UIBarButtonItem, I would create a struct like this:You can use this in a custom
ToolbarContentlike this:In the
bodyof aView, you can then do:NavBarButton.initis main actor-isolated, but so isView.body, so this is okay.