View简介
A type that represents part of your app’s user interface and provides modifiers that you use to configure views.
View
代表应用程序用户界面的一部分并提供用于配置视图的修饰符
public protocol View : _View {
associatedtype Body : View
var body: Self.Body { get }
}
View
协议有一个关联的类型 Body
,它被限制为任何符合 View
协议的类型。body
中是在屏幕上呈现的实际内容。 SwiftUI 将通过 body
计算属性的实现来推断关联的类型。
You create custom views by declaring types that conform to the
View
protocol. Implement the requiredbody
computed property to provide the content for your custom view.
你可以通过声明符合View
协议的类型来创建自定义视图。实现所需的 body
计算属性以为您的自定义视图提供内容,如下:
struct MyView: View {
var body: some View {
Text("Hello, World!")
}
}
some View
这种写法使用了 Swift 5.1 的 Opaque return types
特性。它向编译器作出保证,每次 body
得到的一定是某一个确定的,遵守 View
协议的类型,告诉编译器“不要再细究具体的类型"
Assemble the view’s body by combining one or more of the built-in views provided by SwiftUI, like the
Text
instance in the example above, plus other custom views that you define, into a hierarchy of views. For more information about creating custom views, see Declaring a custom view.
通过将 SwiftUI 提供的一个或多个内置视图(如上例中的 Text 实例)以及你定义的其他自定义视图组合到视图层次结构中来组装视图的body
。有关创建自定义视图的更多信息, 可以看Declaring a custom view.
The
View
protocol provides a set of modifiers — protocol methods with default implementations — that you use to configure views in the layout of your app. Modifiers work by wrapping the view instance on which you call them in another view with the specified characteristics, as described in Configuring views. For example, adding theopacity(_:)
modifier to a text view returns a new view with some amount of transparency:
View
协议提供了一组修饰符 - 具有默认实现的协议方法 - 您可以使用它们来配置应用布局中的视图。修饰符通过将调用它们的视图实例包装在具有指定特征的另一个视图中来工作,如配置视图 中所述。例如,将 opacity(_:)
修饰符添加到文本视图会返回一个包含一定数量的新视图透明度:
Text("Hello, World!")
.opacity(0.5) // Display partially transparent text.
Why is View a struct and not a class anymore?
One of the fundamental principles of SwiftUI is to have a single source of truth in your code. A traditional UIKit approach of having a base UIView class and all other views inherit from it has a demerit wherein we have multiple stored properties in our view inherited from parent UIView. You only define properties that you want to use unlike in UIKit where you inherit a number of properties from your parent view.
SwiftUI
的基本原则之一是在你的代码中拥有单一的事实来源。传统 UIKit 方法有一个基类 UIView
,所有从它继承而来视图都有一个缺点,即我们的视图中有多个存储属性,这些属性是从父 UIView
继承的。而在SwiftUI
中你只定义你想使用的属性,不像在UIKit
中你从父视图继承许多属性
SwiftUI tends to make views pretty lightweight and what better option than a value type with no headache of reference counting and retain cycles. Reference types are messier to maintain. You can alter your properties from anywhere in your code.
Swift UI also makes you be responsible for any views and their own state. Views are independent and isolated from one another. Any changes to a particular view will not affect any other unless they are binded by some common source of truth. It’s allocated on the stack, and it’s passed by value.
SwiftUI
倾向于使视图变得非常轻量级,并且有什么比值类型是更好的选择,无需担心引用计数和循环引用。引用类型更难维护,因为你可以从代码中的任何位置更改属性。
SwiftUI
让你对任何视图和它们自己的状态负责。视图是独立的并且彼此隔离。对特定视图的任何更改都不会影响任何其他视图,除非它们受到某些共同事实来源的约束。它在堆栈上分配,并按值传递。
Simple Example
屏幕上展示一个文本内容,直接使用Text
即可
import SwiftUI
// 定义结构体ContentView,遵守View协议
struct ContentView: View {
// 计算属性body
// some View:表示返回的内容将遵守View协议
var body: some View {
// 返回一个具体类型的View
Text("Hello, World!")
}
}
// 仅仅是用于预览界面效果,最终不会被打包
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
可以在右侧的预览页面看到效果:
self is immutable in View body
struct ContentView: View {
var title: String
var body: some View {
VStack {
Button(action: {
self.title = "I am changing this"
}) {
Text("Hit me")
}
}
}
}
上面代码,我们尝试修改title,将会得到编译错误提示:
这个错误是因为body
是一个计算属性,我们不能从计算属性中改变 self
。那么如何解决?可以使用@State
修饰,将title
作为 @State
属性,那么 SwiftUI
框架会负责对其存储并且可以修改。
@State var title: String