一同养成写作习气!这是我参加「日新计划 4 月更文应战」的第12天,点击查看活动概况。
前言:写这篇文章已经快挨近12点了,写了快2个小时,总的来说,要想讲清楚一个知识点还是没那么简略,首要语言不能太杂乱,不能有太多专有名词,假如有些转有名词避不开,也要想方法举个比如。果然,蜕变的路上总是困难和孤单的。
今日职言:不要企图说服读者,不要以讲道理的方法推进论题。
在本章中,你将学会怎么运用循环遍历的方法创立一个列表,并可自界说参数动态生成列表。
假如你接触过UIKit的话,应该会用过tableView组件创立列表,咱们日子顶用的许多App根本都是列表的方法。
例如的信息列表、手机体系设置、音乐列表等等……
根本上大多数App,特别是资讯类App都少不了列表的存在。
而在SwiftUI中,咱们用List替代了原有tableView,使得代码愈加简练易懂。
由于List组件在不同场景下的运用不同,本章节分成4个部分解说。
1、简略文字列表;
2、图片+文字列表;
3、列表数据整合;
4、Identifiable协议的运用;
榜首部分:简略文字列表
首要,咱们先创立一个新项目,命名为SwiftUIList。
咱们在ContentView.swift文件中,创立一个简略的列表。
List的结构方法和之前学习的VStack很类似,将内容包裹在里边形成列表。
struct ContentView: View {
var body: some View {
//简略的列表
List {
Text(“第1页")
Text(“第2页")
Text(“第3页")
Text(“第4页")
}
}
}
咱们看到List里边都是Text文本,并且仅仅内容不同。
这时候,咱们能够运用ForEach的方法把代码抽离出来,也就不需要写那么多相似的代码。
struct ContentView: View {
var body: some View {
// 简略的列表
List {
ForEach(1 ... 4, id: \.self) { index in
Text("第 \(index)页")
}
}
}
}
在运用ForEach遍历创立视图时,需要用id来标识内容,当里边的内容发现变化时,ForEach就能够主动更新UI。
简略来读一下代码内容:
咱们传递给ForEach一个规模的值,用来循环遍历生成列表。
而它的id(标识符)被设置为值本身self,也便是前面设置的1、2、3、4。
然后用index参数存储循环的值。
咱们在这里遍历了4次,每一次展示一个Text,Text里边的文字是“第”+{index}+“页”,index的参数值从1~4;
这样,咱们就得到了一个列表。
当然,还有更简略的遍历方法。
struct ContentView: View {
var body: some View {
// 简略的列表
List {
ForEach(1 ... 4, id: \.self) {
Text("第 \($0)页")
}
}
}
}
在这里,咱们省掉索引参数index,而运用简化的$0,它引证闭包的榜首个参数,直接将数据集合传递给List。
这样,也能够达到列表的作用,并且使得代码愈加简略。
第二部分:图片+文字列表
好,下面进阶一下,咱们测验完成下面的UI设计稿。
首要剖析下它的结构。
一个列表里,有Image、Text,他们是横向HStack排布。
咱们先在Assets.xcassets导入咱们所需的图片。
并且咱们已经提早给图片命好名了,方便咱们接下来运用它们。
咱们回到ContentView.swift文件中,创立2个数组,寄存咱们的图片和文字。
//界说数组,寄存数据
var myImages = ["weixin","weibo","qq","phone","mail"]
var myNames = ["这是微信","这是微博","这是QQ","这是电话","这是邮箱"]
咱们看到报错了,但又没有彻底报错。
这是由于咱们界说了一个动态数组,但在代码中没有用到,所以体系告知咱们界说的数组称号没有被运用罢了。
没事的,咱们继续。
咱们在body里边创立咱们需要的代码。
struct ContentView: View {
//界说数组,寄存数据
var myImages = ["weixin","weibo","qq","phone","mail"]
var myNames = ["这是微信","这是微博","这是QQ","这是电话","这是邮箱"]
var body: some View {
// 列表
List(myImages.indices, id: \.self) { index in
HStack {
Image(self.myImages[index])
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(self.myNames[index])
}
}
}
}
咱们还是构建了一个列表,不过运用myImages作为目录,也便是myImages.indices。
然后图片遍历用myImages数组,文字遍历用myNames数组。
是不是很简略,比起以前用UIKit的时候,要给cell协议和声明,SwiftUI几行代码就搞定了。
第三部分:列表数据整合
下面,咱们再进阶一下。
上面的代码中,咱们发现假如是图片+文字,那么咱们创立了2个数组,假如是愈加杂乱的场景,咱们岂不是要树立一堆的数组数据?
不不不,这必定不够高雅。
最好的方法应该是,无论咱们多少数组数据,咱们都用一个数组包裹住。
咱们回到UI稿中。
有没有方法,把Image和Text界说出来,然后Image和Text是一个数组?
有的!这时候,咱们需要创立一个结构体,叫做Message,并界说好里边的变量。
代码如下:
struct Message {
var name: String
var image: String
}
运用这个Message结构体,咱们将本来的myImages、myNames数组组合成一个数组。
咱们界说了一个数组Messages,它里边的内容是Message结构体。
代码如下:
// 界说数组,寄存数据
var Messages = [
Message(name: "这是微信", image: "weixin"),
Message(name: "这是微博", image: "weibo"),
Message(name: "这是QQ", image: "qq"),
Message(name: "这是电话", image: "phone"),
Message(name: "这是邮箱", image: "mail")
]
构建好了今后,咱们回到body里边,把里边的引证的参数值换成数组Messages,运用结构体Message遍历数据,List中运用image特点作为仅有的标识符。
一起,要把里边Image的参数引证结构体Message的image参数,Text引证结构体Message的name参数。
代码如下:
// 列表
List(Messages, id: \.image) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
}
}
那么,终究的结果和咱们之前做的作用是相同的。
仅有不相同的是,咱们的代码看起来高雅多了。
小结一下:
咱们创立了一个结构体Message,它界说了2个变量,1个是image图片,是Strring类型,另一个是name称号,也是Strring类型。
然后咱们界说个一个数组Messages(注意加了S),这个数组里边是结构体Message,并赋予了结构体里边2个变量的值;
然后在在body主代码块List里边,用Messages数据作为引证值数据,然后用结构体Message遍历数据。
最终把里边的Image和Text中的值换成结构体中变量的值。
第四部分:Identifiable协议的运用
完成第三部分今后,咱们的代码List就完美了么?
并不!
由于这个:
List(Messages, id: \.image)
咱们运用了image为Messages数组的仅有标识符,也便是List是通过image的仅有性找到对应数组的数据。
这样,咱们会面临一个问题,假如我有2个图片是相同的,但是它的name不相同。
咱们测验把Messages数组的数据换成下面这样:
// 界说数组,寄存数据
var Messages = [
Message(name: "这是微信", image: "weixin"),
Message(name: "这是第二个微信号", image: "weixin")
]
咱们发现,假如咱们运用image作为id,也便是仅有标识符的话。
假如我的数组里有2个image,假如它们的值相同,那么SwiftUI会以为这两个是同一个东西。
也便是,我都是图片都是“微信”,但称号不相同,但计算机以为两个都是微信,并且值相同,这是由于image作为id是仅有的。
这时候,咱们该怎么办?
咱们希望的结果是,Messages数组里,每一个结构体的数据都是仅有的。
那么咱们就不能在body构建仅有的标识符,应该在传值之前就在Message结构体里构建仅有的id。
struct Message {
var id = UUID()
var image: String
var name: String
}
在代码中,咱们添加了id特点,并用仅有标识符初始化它。
UUID()函数用于生成一个全局惟一的随机标识符。
UUID由128位数字组成,因此从理论上讲,具有两个相同标识符的可能性简直为零。
然后,咱们把body代码中的id,引证Message结构体的id。
// 列表
List(Messages, id: \.id) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
}
}
这样,咱们就完成了List数据源的仅有。
再科普一个知识点。
咱们还能够设置结构体Message遵循Identifiable协议。
这样,遵循Identifiable的结构体就能够主动跟踪它的id作为仅有标识符,咱们也就不需要在body中指定id了。
完好代码如下:
import SwiftUI
struct ContentView: View {
// 界说数组,寄存数据
var Messages = [Message(image: "weixin", name: "这是微信"),Message(image: "weixin", name: "我的第二个微信号")]
var body: some View {
// 列表
List(Messages) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Message: Identifiable {
var id = UUID()
var image: String
var name: String
}
恭喜你!完成了List的学习!
假如本专栏对你有帮助,无妨点赞、谈论、关注~