.shadow(radius: 10)
image
通过一个 .shadow
的 modifier,modified
变量的类型将转变为 _ModifiedContent<Image, _ShadowEffect>
。如果你查看 View
上的 shadow
的定义,它是这样的:
extension View {
func shadow(
color: Color = Color(.sRGBLinear, white: 0, opacity: 0.33),
radius: Length, x: Length = 0, y: Length = 0)
-> Self.Modified<_ShadowEffect>
}
Modified
是 View
上的一个 typealias,在 struct Image: View
的实现里,我们有:
public typealias Modified<T> = _ModifiedContent<Self, T>
_ModifiedContent
是一个 SwiftUI 的私有类型,它存储了待变更的内容,以及用来实施变更的 Modifier
:
struct _ModifiedContent<Content, Modifier> {
var content: Content
var modifier: Modifier
}
在 Content
遵守 View
,Modifier
遵守 ViewModifier
的情况下,_ModifiedContent
也将遵守 View
,这是我们能够通过 View
的各个 modifier extension 进行链式调用的基础:
extension _ModifiedContent : _View
where Content : View, Modifier : ViewModifier
{
}
在 shadow
的例子中,SwiftUI 内部会使用 _ShadowEffect
这个 ViewModifier
,并把 image
自身和 _ShadowEffect
实例存放到 _ModifiedContent
里。不论是 image 还是 modifier,都只是对未来实际视图的描述,而不是直接对渲染进行的操作。在最终渲染前,ViewModifier
的 body(content: Self.Content) -> Self.Body
将被调用,以给出最终渲染层所需要的各个属性。
更具体来说,_ShadowEffect
是一个满足 EnvironmentalModifier
协议的类型,这个协议要求在使用前根据使用环境将自身解析为具体的 modifier。
其他的几个修改 View 属性的链式调用与 shadow
的原理几乎一致。
小结
上面是对 SwiftUI 教程的第一部分进行的一些说明,在之后的一篇文章里,我会对剩余的几个教程中有意思的部分再做些解释。
虽然公开还只有一天,但是 SwiftUI 已经经常被用来和 Flutter 等框架进行比较。试用下来,在 view 的描述表现力上和与 app 的结合方面,SwiftUI 要胜过 Flutter 和 Dart 的组合很多。Swift 虽然开源了,但是 Apple 对它的掌控并没有减弱。Swift 5.1 的很多特性几乎可以说都是为了 SwiftUI 量身定制的,我们已经在本文中看到了一些例子,比如 Opaque return types 和 Function builder 等。在接下来对后面几个教程的解读中,我们还会看到更多这方面的内容。
另外,Apple 在背后使用 Combine.framework 这个响应式编程框架来对 SwiftUI.framework 进行驱动和数据绑定,相比于现有的 RxSwift/RxCocoa 或者是 ReactiveSwift 的方案来说,得到了语言和编译器层级的大力支持。如果有机会,我想我也会对这方面的内容进行一些探索和介绍。