此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结
说在前面 每种语言都有类似的属性,就是为了 一次定义,多处复用 的思想,减少代码的冗余。
自定义视图组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import SwiftUIstruct YikunText : View { var text: String var body: some View { Text (text) .foregroundColor(.white) .padding() .background(.blue) } } struct ContentView : View { var body: some View { VStack { YikunText (text: "易困Yikun" ) YikunText (text: "无限进步" ) } } }
这里我们封装了一个结构体 YikunText ,然后就可以直接使用这个封装好的组件,与ContentView的区别不大,都遵循了 View 协议,目的是为了将视图的样式和布局代码进行封装,提高代码的复用性,在前端代码里很常见,比如三框架中就叫做组件 components 。
ViewModifier 视图修改器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import SwiftUIstruct YikunText : ViewModifier { func body (content : Content ) -> some View { content .foregroundColor(.white) .padding() .background(.blue) } } struct ContentView : View { var body: some View { VStack { Text ("易困Yikun" ) .modifier(YikunText ()) Text ("无限进步" ) .modifier(YikunText ()) } } }
这次我们使用 ViewModifier 实现了相同的效果,它们的目的相同,都是为了方便地修改和定制视图。
定义方式不同:
自定义视图(如YikunText):通过定义一个遵循View协议的结构体来创建自定义视图。这个结构体有一个body计算属性,用于返回视图内容。在body中可以直接组合和定制多个视图,并设置它们的样式。
ViewModifier:通过定义一个遵循ViewModifier协议的结构体来创建。这个结构体需要实现一个 body(content: Content) -> some View 方法,其中 content 是要被修改的视图,方法返回修改后的视图。
应用方式不同:
自定义视图(如YikunText):通过创建自定义视图结构体的实例来使用。在其他视图中,可以像使用普通视图一样使用自定义视图,如在ContentView中使用 YikunText(text: “易困Yikun”) 。
ViewModifier:通过视图的.modifier()方法来应用,如 Text(“易困Yikun”).modifier(YikunText()) 。
结合扩展extension来实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import SwiftUIstruct YikunText : ViewModifier { func body (content : Content ) -> some View { content .foregroundColor(.white) .padding() .background(.blue) } } extension View { func titleStyle () -> some View { modifier(YikunText ()) } } struct ContentView : View { var body: some View { VStack { Text ("易困Yikun" ) .titleStyle() Text ("无限进步" ) .titleStyle() } } }
这种写法同样能实现上面的效果,它是利用 ViewModifier 来创建可复用的视图样式修改逻辑,并通过扩展(extension)为 View 类型添加了一个便捷的方法,使得多个视图能够方便地应用该样式。
结合上面实例实现水印效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import SwiftUIstruct YikunText : ViewModifier { func body (content : Content ) -> some View { content .foregroundColor(.white) .padding() .background(.blue) } } struct Watermark : ViewModifier { var text: String func body (content : Content ) -> some View { ZStack (alignment: Alignment .bottomTrailing){ content Text (text) .font(.caption) .foregroundColor(.white) .padding(5 ) .background(.black) } } } extension View { func titleStyle () -> some View { modifier(YikunText ()) } func watermarked (with text : String ) -> some View { modifier(Watermark (text: text)) } } struct ContentView : View { var body: some View { VStack { Text ("无限进步" ) .frame(width: 100 ,height: 100 ) .titleStyle() .watermarked(with: "易困Yikun" ) } } }
Watermark 结构体部分:
同样遵循 ViewModifier 协议,并且额外接收一个 text 参数。
在 body 方法中,使用 ZStack 进行视图叠加布局,先放置传入的原始 content 视图,然后在右下角(通过 Alignment.bottomTrailing 对齐方式)添加一个文本水印。水印文本具有特定的样式,如设置为小字号(.caption 字体)、白色前景色、添加内边距以及黑色背景,实现了为视图添加自定义文本水印的功能。
高级进阶 网格布局 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import SwiftUIstruct GridStack <Content : View >: View { let rows: Int let columns: Int @ViewBuilder let content: (Int , Int ) -> Content var body: some View { VStack { ForEach (0 ..< rows, id:\.self ){ row in HStack { ForEach (0 ..< columns,id:\.self ){ column in content(row, column) } } } } } } struct ContentView : View { var body: some View { GridStack (rows: 4 , columns: 4 ){ row, col in Image (systemName: "\(row* 4 + col) .circle" ) Text ("R\(row) C\(col) " ) } } }
知识点
泛型编程: 使用泛型来定义 GridStack 结构体,使得它可以处理不同类型的视图作为其内部单元格内容,提高了代码的复用性和通用性。这是一种很重要的编程思想,能够避免为不同的视图类型编写重复的相似代码,只要这些视图遵循 View 协议即可融入到 GridStack 的布局当中。
视图构建与组合:
通过 VStack 和 HStack 以及 ForEach 循环的配合,展示了如何在 SwiftUI 中动态地构建复杂的视图布局结构。利用 ForEach 可以方便地根据数据(这里是行和列的索引)来重复生成视图元素,然后通过嵌套的布局容器将这些元素组合成想要的布局形式,比如这里构建出了网格布局。
@ViewBuilder 属性包装器的运用,让闭包内构建视图变得更加简洁直观,它允许像在普通视图结构体的 body 里那样书写视图代码,使得代码的可读性更好,也符合 SwiftUI 中视图构建的语法习惯。
尾随闭包语法: 在 ContentView 中创建 GridStack 实例时使用了尾随闭包语法,将原本应该写在括号内的闭包参数移到了括号外面,使代码更加简洁、易读,尤其是当闭包内容较多、逻辑较复杂时,这种语法能让代码结构更加清晰,是 Swift 语言中一种常用的提高代码可读性的语法特性。。