#xcode #swiftui
Вопрос:
Я поддерживаю iOS 13 и выше. Я хочу использовать новый .toolbar
модификатор для дополнительной функции на устройствах, использующих iOS 14 и выше. Я использую Xcode 13.0 RC 1, сборка 13A233, но проблема также возникает в Xcode 12.5.1. Я создал следующий код:
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()
}
}
}
}
}
Я включил бит предварительного просмотра, поэтому все вышесказанное можно вставить в пустой файл в любом проекте Xcode SwiftUI. Это работает. Когда я раскомментирую ToolbarItem
инструкцию, я получаю следующие ошибки:
Static method 'buildBlock' requires that 'ToolbarItem<Void, Text>' conform to 'View'
Static method 'buildLimitedAvailability' requires that 'ToolbarItem<Void, Text>' conform to 'View'
Как я могу исправить эти ошибки?
Ответ №1:
Я думаю, что основная проблема заключается в том, что блок .toolbar
модификатора определен так, чтобы возвращать что-то, соответствующее ToolbarContent
протоколу. Из документов:
func toolbar<Content>(content: () -> Content) -> some View where Content : ToolbarContent
Как таковой, в вашем модификаторе представления
func body(content: Content) -> some View {
if #available(iOS 14.0, *) {
content
.toolbar(content: self.toolbarContent)
}
}
… вам нужно убедиться, что self.toolbarContent
это соответствует () -> ToolbarContent
подписи этого типа.
Просто взглянув на ваш код, я был бы склонен сначала попробовать изменить ваше соответствие T
с T: View
на T: ToolbarContent
. На первый взгляд этого может быть достаточно, но, возможно, вам потребуется еще немного поработать, чтобы все привести в порядок.