Статический метод «buildBlock» требует, чтобы » Панель инструментов» соответствовала «Представлению»

#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 . На первый взгляд этого может быть достаточно, но, возможно, вам потребуется еще немного поработать, чтобы все привести в порядок.