前言
在swiftui框架中使用很多的注解,虽然使语法看上去非常简洁,但是增加了初学者的理解难度,这篇文章我们来看一下@viewbuilder的相关知识。主要包括以下内容:
- resultbuilder/functionbuilder是什么以及用法
- viewbuilder结构体
- @viewbuilder修饰符的用法
- 使用@viewbuilder完成一个自定义视图
@resultbuilder注解
@resultbuilder是在swift5.4添加的,之前是叫@_functionbuilder,在这里我们可以简单了解一下它的作用。
一个类、结构体添加@resultbuilder注解时必须包含至少一个buildblock方法,并且这个方法是static静态的。这个方法可以接收0个或多个参数,在函数内部确定了参数的组成形式。
比如下面这个例子:
@resultbuilder struct stringbuilder { static func buildblock(_ string1: string, _ string2: string, _ string3: string) -> string { string1 " - " string2 " - " string3 } } func test(@stringbuilder strings: () -> string) { print(strings()) } test { "1" "2" "3" }
stringbuilder是一个字符串构建者结构体,里面的buildblock方法接收3个参数,并且在3个参数中间插入” - “作为函数的返回值。
test函数接收一个使用@stringbuilder修饰的名为strings的闭包作为参数,函数体是调用这个闭包并打印到控制台。
最后使用3个字符串作为参数调用test函数,执行这段代码后会得到”1 - 2 - 3”的输出结果
@viewbuilder定义
先来看viewbuilder的定义:
@resultbuilder struct viewbuilder
viewbuilder本质上是一个结构体,并且被@resultbuilder注解,也就是说viewbuilder是一个reult builder(结果建造者)类型了。
viewbuilder结构体有11个名为buildblock的函数,分别接收从0到10个view类型的参数,因此在swiftui中一个接收@viewbuilder类型参数的视图容器最多能接收10个子视图,如果不能满足需求可以通过拆分来增加子视图的个数。
@viewbuilder的用法
使用@resultbuilder注解viewbuilder结构体后,就可以用@viewbuilder修饰闭包,这个闭包可以接收多个指定类型的对象,而这些对象会按照buildblock函数的实现进行组织。
a custom parameter attribute that constructs views from closures.
这是apple的官方文档对viewbuilder的定义,简单来说viewbuilder就是一个包含多个视图的闭包。
在swiftui框架中,所有的容器视图都是使用@viewbuilder来修饰最后一个参数,因此这些容器视图可以接受多个子视图作为参数。比如hstack/vstack/scrollview等。
// hstack public struct hstack: view where content : view { ... @inlinable public init(alignment: verticalalignment = .center, spacing: cgfloat? = nil, @viewbuilder content: () -> content) ... }
这是hstack的初始化方法,其中前面的几个参数都是可选项,它们不在本篇文章的讨论范围内。
它的最后一个参数content的类型是一个返回值为content的闭包,单看()->content是一个没有参数的闭包,但是前面使用了@viewbuilder修饰,这就是一个可以接收多个视图的闭包了,最终看起来像是这样的:(view1: content, view2: content....) -> content。
下面我们通过自定义一个视图来看@viewbuilder的用法。
实践
下面通过实现一个自定义的容器视图来展示@viewbuilder的用法:
@viewbuilder示例
自定义一个继承自view名为customcontainerview的视图,它仅有一个接收@viewbuilder类型参数的初始化方法,并使用常量content接收这个参数。
在body中构建当前视图:@viewbuilder中可能包含多个子视图,因此使用vstack把这些子视图纵向排列,之后使用多个视图修改器自定义子视图的外观。
在源文件的第29行,contentview中创建了customcontainerview并给它传递了3个text子视图。通过xcode右侧的即时预览可以看到这三个子视图正是以我们在customcontainerview中要求的方式展现出来——纵向排列、绿色的背景色、红色的文字颜色等。
总结
至此,关于@viewbuilder的相关知识基本都涉及到了,相信通过本篇文章的学习你一定也对它有了一个非常全面的掌握,那么赶快到实战项目中用起来吧👍。