I'm supporting iOS 13 and up. I wish to use the new .toolbar modifier for an optional feature, in devices using iOS 14 and up. I'm using Xcode 13.0 RC 1, build 13A233, but the issue also occurs in Xcode 12.5.1. I have created the following code:
import SwiftUI
struct MyToolbar<T>: ViewModifier where T: View {
let toolbarContent: () -> T
func body(content: Content) -> some View {
if #available(iOS 14.0, *) {
content
.toolbar(content: self.toolbarContent)
}
}
}
extension View {
func myToolbar<T: View>(@ViewBuilder content: @escaping () -> T) -> some View {
self.modifier(MyToolbar(toolbarContent: content))
}
}
struct MyToolbar_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
Text("Hello, world")
.myToolbar {
if #available(iOS 14.0, *) {
Text("Hello, world!")
// ToolbarItem(placement: .bottomBar) {
// Text("Hello, world!")
// }
} else {
EmptyView()
}
}
}
}
}
I have included the preview bit, so the above can be pasted into an empty file in any Xcode SwiftUI project. It works. When I uncomment the ToolbarItem statement, I get the following errors:
Static method 'buildBlock' requires that 'ToolbarItem<Void, Text>' conform to 'View'
Static method 'buildLimitedAvailability' requires that 'ToolbarItem<Void, Text>' conform to 'View'
How can I fix these errors?
You can use the @ToolbarContentBuilder
extension View {
@ToolbarContentBuilder
func toolbarContent() -> some ToolbarContent {
...
}
You can add your extension like this
func body(content: Content) -> some View {
if #available(iOS 14.0, *) {
content
.toolbar(content: self.toolbarContent)
}
}
I think the main issue is that the .toolbar modifier's block is defined to return something conforming to the ToolbarContent protocol. From the docs:
func toolbar<Content>(content: () -> Content) -> some View where Content : ToolbarContent
As such, within your view modifier
func body(content: Content) -> some View {
if #available(iOS 14.0, *) {
content
.toolbar(content: self.toolbarContent)
}
}
… you need to ensure that self.toolbarContent matches that () -> ToolbarContent type signature.
Just from glancing at your code, I'd be inclined to first try changing your conformance of T from T: View to T: ToolbarContent. By eye that looks like it might be enough, but it's possible you might need to do a bit more work to tidy everything up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With