Adquira o hábito de escrever juntos! Este é o 12º dia da minha participação no "Nuggets Daily New Plan · April Update Challenge", clique para ver os detalhes do evento .
Prefácio: São quase 12 horas da redação deste artigo, e ele foi escrito por quase 2 horas. Em geral, não é tão simples explicar claramente um ponto de conhecimento. Em primeiro lugar, a linguagem não deve ser muito complicado, e não deve haver muitos nomes próprios. , se houver substantivos que não podem ser evitados, tente encontrar uma maneira de dar um exemplo. Com certeza, o caminho para a transformação é sempre difícil e solitário.
Palavra do dia: Não tente convencer os leitores, não avance o tópico de forma sensata.
Neste capítulo, você aprenderá como criar uma lista usando a travessia de loop e gerar listas dinamicamente com parâmetros personalizados.
Se você foi exposto ao UIKit, deve ter usado o componente tableView para criar listas. Muitos dos aplicativos que usamos em nossas vidas são basicamente na forma de listas.
Por exemplo, a lista de informações do Nuggets, configurações do sistema de telefonia móvel, lista de músicas, etc...
Basicamente, a maioria dos aplicativos, especialmente aplicativos de informação, possui listas.
No SwiftUI, substituímos o tableView original por List, o que torna o código mais conciso e fácil de entender.
Devido às diferentes aplicações do componente Lista em diferentes cenários, este capítulo é dividido em 4 partes para explicar.
1. Lista de texto simples;
2. Lista de imagens + texto;
3. Integração de dados da lista;
4. Utilização do protocolo Identificável;
Parte 1: Lista de Texto Simples
Primeiro, vamos criar um novo projeto chamado SwiftUIList.
Criamos uma lista simples no arquivo ContentView.swift.
A construção de List é muito semelhante ao VStack que aprendemos antes, envolvendo o conteúdo nele para formar uma lista.
struct ContentView: View {
var body: some View {
//简单的列表
List {
Text(“第1页")
Text(“第2页")
Text(“第3页")
Text(“第4页")
}
}
}
复制代码
Vemos que a Lista está cheia de texto Texto, e apenas o conteúdo é diferente.
Neste momento, podemos usar ForEach para extrair o código, então não precisamos escrever tantos códigos semelhantes.
struct ContentView: View {
var body: some View {
// 简单的列表
List {
ForEach(1 ... 4, id: \.self) { index in
Text("第 \(index)页")
}
}
}
}
复制代码
Ao usar ForEach para atravessar para criar uma exibição, você precisa usar id para identificar o conteúdo. Quando o conteúdo dentro muda, ForEach pode atualizar automaticamente a interface do usuário.
Basta ler o conteúdo do código:
Passamos para ForEach um intervalo de valores para percorrer a lista gerada.
E seu id (identificador) é definido para o próprio valor, que é 1, 2, 3, 4 definido anteriormente.
然后用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
}
复制代码
No código, adicionamos a propriedade id e a inicializamos com um identificador único.
A função UUID() é usada para gerar um identificador aleatório globalmente exclusivo.
Os UUIDs são compostos de números de 128 bits, portanto, teoricamente, a chance de ter dois identificadores idênticos é praticamente nula.
Em seguida, usamos o id no código do corpo para nos referirmos ao id da estrutura Message.
// 列表
List(Messages, id: \.id) { Message in
HStack {
Image(Message.image)
.resizable()
.frame(width: 40, height: 40)
.cornerRadius(5)
Text(Message.name)
}
}
复制代码
Dessa forma, concluímos a exclusividade da fonte de dados List.
Mais um ponto de conhecimento.
Também podemos definir a estrutura Message para seguir o protocolo Identificável.
Dessa forma, um struct que está em conformidade com Identifiable pode rastrear automaticamente seu id como um identificador exclusivo e não precisamos especificar um id no corpo.
O código completo é o seguinte:
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
}
复制代码
Parabéns! Completou o aprendizado da Lista!
Se esta coluna for útil para você, por favor, curta, comente e siga~