前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >为什么SwiftUI修饰符顺序很重要?

为什么SwiftUI修饰符顺序很重要?

作者头像
韦弦zhy
发布2020-03-26 22:13:11
2.4K0
发布2020-03-26 22:13:11
举报
文章被收录于专栏:韦弦的偶尔分享

每当我们将修饰符应用于SwiftUI视图时,我们实际上都会创建一个应用了更改的新视图——我们不仅会修改现有的视图。如果您考虑一下,这种行为是有道理的——我们的视图仅保留我们赋予它们的确切属性,因此,如果我们设置背景颜色或字体大小,则无处存储该数据。

我们将在下一章中查看为什么会发生这种情况,但是首先,我想看看这种行为的实际含义。看一下这段代码:

代码语言:javascript
复制
Button("Hello World") {
    // do nothing
}    
.background(Color.red)
.frame(width: 200, height: 200)

您认为它运行时会是什么样?

您很可能猜错了:您不会在中间看到带有“ Hello World”的200x200红色按钮。相反,您会看到一个200x200的空正方形,中间是“ Hello World”,在“ Hello World”周围有一个红色矩形。

如果思考一下修饰符的工作原理,您就可以了解为什么会如此:每个修饰符都会创建一个应用了该修饰符的新结构体,而不是在视图上设置属性。

您可以通过查询视图主体的类型来窥视SwiftUI的底层。将按钮修改为如下:

代码语言:javascript
复制
Button("Hello World") {
    print(type(of: self.body))
}    
.background(Color.red)
.frame(width: 200, height: 200)

Swift的type(of:)方法会打印特定值的确切类型,在这种情况下,它将打印以下内容:ModifiedContent<ModifiedContent<Button<Text>, _BackgroundModifier<Color>>, _FrameLayout>

您可以在这里看到两件事:

  • 每次我们修改视图时,SwiftUI都会使用以下泛型来应用该修饰符:ModifiedContent<OurThing, OurModifier>
  • 当我们应用多个修饰符时,它们会叠加在一起:ModifiedContent<ModifiedContent<…

要了解该类型是什么,请从最里面的类型开始,然后逐步解决:

  • 最里面的类型是ModifiedContent<Button<Text>, _BackgroundModifier<Color>:您的按钮上有一些带有背景色的文本。
  • 在外部,我们有了ModifiedContent<…, _FrameLayout>,它使用了我们的第一个视图(按钮+背景色),并为其提供了Frame。

如您所见,我们使用ModifiedContent类型堆叠——每个视图都需要一个视图进行转换以及要进行的实际更改,而不是直接修改视图。

这意味着修饰符的顺序很重要。如果我们重写代码以在设置Frame后应用背景色,那么您就会得到预期的结果:

代码语言:javascript
复制
Button("Hello World") {
    print(type(of: self.body))
}
.frame(width: 200, height: 200)
.background(Color.red)

现在最好的思考方法是,想象一下SwiftUI在每个修饰符之后都会呈现您的视图。因此,只要您说 .background(Color.red),它就会将背景颜色变为红色,而不管您给它什么Frame。如果您之后再扩展Frame,它将不会神奇地重绘已经应用了的背景。

使用修饰符的一个重要副作用是,我们可以多次应用相同的效果:每个修饰符都会简单地添加到以前的内容中。

例如,SwiftUI为我们提供了padding()修饰符,该修饰符在视图周围添加了一些空间,从而不会将其推到其他视图或屏幕边缘。如果我们应用填充,然后应用背景色,然后应用更多填充和不同的背景色,则可以为视图提供多个边框,如下所示:

代码语言:javascript
复制
Text("Hello World")
    .padding()
    .background(Color.red)
    .padding()
    .background(Color.blue)
    .padding()
    .background(Color.green)
    .padding()
    .background(Color.yellow)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档