作为其他视图容器的大多数SwiftUI视图都根据它们所包含的内容类型实现为泛型。例如,SwiftUI的内置按钮有一个通用label类型,它决定了每个实例将使用哪种类型的视图进行渲染:
struct Button<Label>: View where Label: View {
...
}
由于SwiftUI视图归根结底只是常规的结构体,我们可以在处理它们时使用与在其他上下文中相同的泛型编程技术。例如,我们可以使用通用的约束来实现专门的便利api——就像下面这个例子,通过使用给定的系统映像作为图标,可以很容易地创建一个按钮
extension Button where Label == Image {
init(iconName: String, action: @escaping () -> Void) {
self.init(action: action) {
Image(systemName: iconName)
}
}
}
泛型类型约束很酷的一点是,编译器会根据每个调用站点自动推断要使用哪种专门化 - 这意味着我们可以调用我们的new Button convenience initializer,而不需要手动输入Button
struct PlayerView: View {
...
var body: some View {
...
Button(iconName: "play.fill") {
startPlayback()
}
}
}
Swift大量使用了Swift的类型系统及其泛型功能,这意味着通常有很多机会创建非常轻量级的api,而不必每次都定义新的视图类型。