文章

声明自定视图

定义视图并将它们组合成一个视图层次结构。

概览

SwiftUI 为用户界面设计提供一种声明的方法。在使用传统的命令式方法时,您的控制器代码不仅要担负视图实例化、布局和配置的任务,还要随着条件发生变化持续进行更新。相比之下,借助声明式方法,您可以通过声明视图来创建用户界面的轻量级描述,视图的层级结构反映了所需的界面布局。然后,SwiftUI 会管理这些视图的绘制和更新以响应用户输入和状态更改等事件。

方块图并排展示视图层次结构以及 iPhone 上该层次结构的相应渲染效果。该层次结构由包含两个文本视图的垂直 stack 组成,第一个文本视图有一个应用标题字体的 font 修饰符。在渲染的输出中,第一个文本视图看起来比第二个大,因为第二个使用的是默认正文字体。

SwiftUI 提供用于在用户界面中定义和配置视图的工具。通过 SwiftUI 提供的原生视图以及您已定义的其他复合视图构建自定视图。使用视图修饰符配置这些视图,并将它们与您的数据模型进行关联。然后,将自定视图放置在您的 app 的视图层次结构中。

遵从 View 协议

通过定义一个遵从 View (英文) 协议的结构来声明自定视图类型:

 struct MyView: View { }
					

与其他 Swift 协议 (英文) 一样,View (英文) 协议提供一个功能蓝图,在本例中是 SwiftUI 在屏幕上绘制的元素的行为。协议的遵从包含了两个方面,视图必须满足的要求以及协议提供的功能。在满足要求后,您可以将自定视图插入视图层次结构中,以使它成为您的 app 用户界面的一部分。

声明 Body

View (英文) 协议的主要要求是遵从类型必须定义一个 body (英文) 计算属性 (英文)

 struct MyView: View {  var body: some View {  } }
					

SwiftUI 会在需要更新视图的任何时候读取此属性的值,这在视图的生命周期中可能重复发生,通常用来响应用户输入或系统事件。视图返回的值是 SwiftUI 在屏幕上绘制的一个元素。

View (英文) 协议的次要要求是遵从类型必须为 body 属性指明一个关联类型 (英文)。然而,您不是进行显式声明,而是使用 some View 语法将 body 属性声明为不透明类型 (英文),以仅指明该 body 的类型符合 View (英文)。确切类型取决于 body 的内容,该内容会随着您在开发期间编辑 body 而变化。Swift 会自动推断确切类型。

组合视图的内容

通过将内容添加到视图的 body 属性来描述您的视图的外观。您可以从 SwiftUI 提供的原生视图以及您在其他地方定义的自定视图编写 body。例如,您可以使用内建的 Text (英文) 视图创建一个绘制字符串“Hello, World!”的 body:

 struct MyView: View {  var body: some View {  Text("Hello, World!")  } }
					

渲染文本视图的截屏,其中显示了采用正文字体的文本“Hello World”。

除了用于特定内容、控件和指示器类型的视图外,例如 Text (英文)Toggle (英文)ProgressView (英文),SwiftUI 还会提供您可用来排列其他视图的原生视图。例如,您可以使用 VStack (英文) 垂直堆叠两个 Text (英文) 视图:

 struct MyView: View {  var body: some View {  VStack {  Text("Hello, World!")  Text("Glad to meet you.")  }  } }
					

两个渲染文本视图的截屏,一上一下分别显示了文本“Hello World”和文本“Glad to meet you”。这两个视图都是以正文字体渲染的。

采用多个输入子视图的视图 (例如,上述示例中的 stack) 通常使用一个以 ViewBuilder (英文) 属性标记的闭包来执行此操作。这样可形成在调用点不需要附加语法的多语句闭包。您仅需要连续列出输入视图。

有关可用容器视图的完整列表,以及它们的用法详情,请参阅“视图布局与呈现 (英文)”。

使用修饰符配置视图

若要在视图的 body 中配置视图,可以应用视图修饰符。修饰符只是一种在特定视图上调用的方法。此方法返回一个全新、更改后的视图,以有效地取代视图层次结构中的原始视图。

为此,SwiftUI 通过一个大型方法集扩展了 View (英文) 协议。只要遵从 View (英文) 协议,不管是原生视图还是自定视图,都可使用这些以某种方式改变视图行为的方法。例如,您可以通过应用 font(_:) (英文) 修饰符更改文本视图的字体:

 struct MyView: View {  var body: some View {  VStack {  Text("Hello, World!")  .font(.title)  Text("Glad to meet you.")  }  } }
					

两个渲染文本视图的截屏,一上一下分别显示了文本“Hello World”和文本“Glad to meet you”。上方的文本以较大的标题字体显示,而下方的文本则使用较小的正文字体。

有关视图修饰符的工作原理以及如何在视图上使用它们的更多信息,请参阅“配置视图”。

管理数据

若要为您的视图提供输入,请添加属性。例如,您可以使“Hello, World!”字符串的字体变为可配置:

 struct MyView: View {  let helloFont: Font    var body: some View {  VStack {  Text("Hello, World!")  .font(helloFont)  Text("Glad to meet you.")  }  } }
					

如果输入值发生变化,SwiftUI 会注意到这种变化并仅重新绘制受影响的界面部分。这可能涉及重新初始化整个视图,但是 SwiftUI 会为您处理此操作。

由于系统可能会随时重新初始化视图,因此,请务必避免在视图的初始化代码中进行任何重要的工作。通常最好的做法是忽略显式构造器,如上例所示,从而让 Swift 可以合成逐一成员构造器来代替它。

SwiftUI 提供了许多工具来帮助您在这些约束下管理您的 app 数据,如“状态和数据流 (英文)”中所述。有关 Swift 构造器的信息,请参阅“Swift 编程语言”中的“初始化 (英文)”。

将视图添加到视图层次结构

在定义视图后,您可以将其并入其他视图,就像您对原生视图执行的操作一样。要添加视图,您可以在层次结构中想要视图出现的位置声明视图。例如,您可以将 MyView 置于您的 app 的 ContentView 中,这样 Xcode 将自动创建它作为新的 app 的根视图:

 struct ContentView: View {  var body: some View {  MyView(helloFont: .title)  } }
					

或者,您可以将视图添加为您的 app 中某个新场景的根视图,例如,声明 macOS 偏好设置窗口内容的 Settings (英文) 场景,或声明 watchOS 通知内容的 WKNotificationScene (英文) 场景。有关使用 SwiftUI 定义 app 结构的更多信息,请参阅“App 结构和行为 (英文)”。

另请参阅

自定视图