We begin by following this example look at Swift 5.1 new features have been studied in SwiftUI in: some
SwiftUI and Swift 5.1 New Features (1) opaque return type Opaque the Result Type , as well as @State
and @Binding
behind @propertyDelegate
SwiftUI and Swift 5.1 New Features (2) Properties Delegates agent Property , and @dynamicMemberLookup
SwiftUI and Swift 5.1 new Features (3) Key Path Member Lookup
struct SlideViewer: View {
@State private var isEditing = false
@Binding var slide: Slide
var body: some View {
VStack {
Text("Slide #\(slide.number)")
if isEditing {
TextFiled($slide.title)
}
}
}
}
复制代码
We finally came to the last important characteristic SwiftUI contained: FunctionBuilder, put the last one in terms of the reason is because it is so far still has not passed a language feature Swift Evolution review, in order to catch Apple WWDC 19 point in time, and therefore still dealing with the spot, so the details discussed in this article may change in the future, but due to the impending release of iOS 13, should not reinvent the wheel.
1. SwiftUI DSL needs
We need to carefully analyze the syntax of the above DSL code:
- Degenerate from the expression: possible unnecessary commas, return, brackets and the like.
- It supports simple logic control, if such control statements.
- Strongly typed:
some View
represents a composite of strongly typed, when View is changed, the composite of strongly typed help make View diff optimization. - Swift existing syntax and do not conflict.
2. to understand @_functionBuilder by ViewBuilder
Like @propertyDelegate
used to modify State
the same, @_functionBuilder
used to decorate ViewBuilder
, there is also ViewBuilder
nothing but a compiler will use it, and there are certain types of requirements for the methods it contains. So ViewBuilder
where is it? In fact, the final closure of the parameters of the various types of containers to VStack
an example:
// 定义
struct VStack<Content> where Content : View {
init(alignment: HorizontalAlignment = .center, spacing: Length? = nil,
@ViewBuilder content: () -> Content)
}
// 使用
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
Text("Hello, World")
Text("Leon Lu")
}
}
}
复制代码
In the above example, we can see how the tile SwiftUI properties comprising in one container type; closure function definition, we see the modified ViewBuidler. It is not difficult to infer, in order to be able compiled, ViewBuidler for the closure of the code at compile time "move the hands and feet", then this is how to do it? The key method ViewBuilder view of:
static func buildBlock() -> EmptyView
static func buildBlock<Content>(Content) -> Content
static func buildBlock<C0, C1>(C0, C1) -> TupleView<(C0, C1)>
static func buildBlock<C0, C1, C2>(C0, C1, C2) -> TupleView<(C0, C1, C2)>
static func buildBlock<C0, C1, C2, C3>(C0, C1, C2, C3) -> TupleView<(C0, C1, C2, C3)>
static func buildBlock<C0, C1, C2, C3, C4>(C0, C1, C2, C3, C4) -> TupleView<(C0, C1, C2, C3, C4)>
...
复制代码
Our two Text
examples, the compiler automatically (by convention the name) using a static func buildBlock<C0, C1>(C0, C1) -> TupleView<(C0, C1)>
method, this time the VStack
kind of became VStack<TupleView<(Text,Text)>>
a. After ViewBuilder
the conversion code:
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
ViewBuilder.buildBlock(Text("Hello, World"), Text("Leon Lu"))
}
}
}
复制代码
It is worth mentioning that, due to buildBlock
the overload of generic versions of most parameters is 10. So when more than 10 can be used when Group
the package it; if there are cycles can be expanded, you can use ForEach
.
3. FunctionBuilder case the branch condition
ViewBuilder
There are two types of functions is used to construct containing the branch condition when
static func buildEither<TrueContent, FalseContent>(first: TrueContent) ->
ConditionalContent<TrueContent, FalseContent>
static func buildEither<TrueContent, FalseContent>(second: FalseContent) ->
ConditionalContent<TrueContent, FalseContent>
复制代码
If the returned different views based on different criteria, then the type included in the generated two types.
struct SlideViewer: View {
@State private var isEditing = false
@Binding var slide: Slide
var body: some View {
VStack {
Text("Slide #\(slide.number)")
if isEditing {
TextFiled($slide.title)
} else {
Text(slide.title)
}
}
}
}
复制代码
In this case, VStack
the type becomesVStack<TupleView<(Text, ConditionalContent<TextField,Text>)>>
Epilogue
From the naming @_functionBuilder
underlined contained can be seen, Function as well as the possibility of some fine-tuning Builder, and therefore the text to the perspective of pragmatism ViewBuilder to introduce what Function Builder Yes.
SwiftUI and Swift 5.1 New Features series so far temporarily paragraph, if necessary, will continue to update and supplement.
Thank you for the love, in the future there will be more articles to bring you, hope you like it.
related articles:
Swift 5.1 SwiftUI and new features (1) Opaque Opaque Result Type Return Type
SwiftUI and Swift 5.1 New Features (2) the property broker Property Delegates
SwiftUI and Swift 5.1 New Features (3) Key Path Member Lookup
Scanning the next Fanger Wei code, concerned about "the interviewer Kin"
Reproduced in: https: //juejin.im/post/5d0b2fa45188252e2e078170