SwiftUI Minimalist Tutorial 12: Uso de List y ForEach Loop

¡Acostúmbrate a escribir juntos! Este es el día 12 de mi participación en el "Nuevo plan diario de Nuggets · Desafío de actualización de abril", haga clic para ver los detalles del evento .

Prólogo: Son casi las 12 en punto en la redacción de este artículo, y se ha escrito durante casi 2 horas. En general, no es tan simple explicar un punto de conocimiento con claridad. En primer lugar, el lenguaje no debe ser demasiado complicado, y no debe haber demasiados nombres propios. , si hay sustantivos que no se pueden evitar, trate de encontrar una manera de dar un ejemplo. Efectivamente, el camino hacia la transformación siempre es difícil y solitario.

Palabra del día: No trate de convencer a los lectores, no avance el tema de manera sensata.

En este capítulo, aprenderá cómo crear una lista utilizando loop traversal y generar listas dinámicamente con parámetros personalizados.

Si ha estado expuesto a UIKit, debería haber usado el componente tableView para crear listas.Muchas de las aplicaciones que usamos en nuestras vidas son básicamente en forma de listas.

Por ejemplo, la lista de información de los Nuggets, la configuración del sistema del teléfono móvil, la lista de música, etc...

214.png

Básicamente, la mayoría de las aplicaciones, especialmente las aplicaciones de información, tienen listas.

En SwiftUI, reemplazamos el tableView original con List, lo que hace que el código sea más conciso y fácil de entender.

Debido a las diferentes aplicaciones del componente Lista en diferentes escenarios, este capítulo se divide en 4 partes para explicar.

1. Lista de texto simple;

2. Imagen + lista de texto;

3. Lista de integración de datos;

4. Uso del protocolo Identificable;

Parte 1: Lista de texto simple

Primero, creemos un nuevo proyecto llamado SwiftUIList.

194.png

Creamos una lista simple en el archivo ContentView.swift.

La construcción de List es muy similar al VStack que aprendimos antes, envolviendo el contenido en él para formar una lista.

struct ContentView: View {
    var body: some View {

        //简单的列表
        List {
            Text(“第1页")
            Text(“第2页")
            Text(“第3页")
            Text(“第4页")
        }
    }
}
复制代码

195.png

Vemos que la Lista está llena de texto Texto, y solo el contenido es diferente.

En este momento, podemos usar ForEach para extraer el código, por lo que no necesitamos escribir tantos códigos similares.

struct ContentView: View {
    var body: some View {

        // 简单的列表
        List {
            ForEach(1 ... 4, id: \.self) { index in
                Text("第 \(index)页")
            }
        }
    }
}
复制代码

196.png

Al usar ForEach para atravesar para crear una vista, debe usar id para identificar el contenido. Cuando el contenido interior cambia, ForEach puede actualizar automáticamente la interfaz de usuario.

Solo lee el contenido del código:

Pasamos a ForEach un rango de valores para recorrer la lista generada.

Y su id (identificador) ​​se establece en el valor en sí, que es 1, 2, 3, 4 establecido anteriormente.

然后用index参数存储循环的值。

我们在这里遍历了4次,每一次展示一个Text,Text里面的文字是“第”+{index}+“页”,index的参数值从1~4;

这样,我们就得到了一个列表。

当然,还有更简单的遍历方法。

struct ContentView: View {
    var body: some View {

        // 简单的列表
        List {
            ForEach(1 ... 4, id: \.self) {
                Text("第 \($0)页")
            }
        }
    }
}
复制代码

197.png

在这里,我们省略索引参数index,而使用简化的$0,它引用闭包的第一个参数,直接将数据集合传递给List。

这样,也可以达到列表的效果,而且使得代码更加简单。

第二部分:图片+文字列表

好,下面进阶一下,我们尝试完成下面的UI设计稿。

207.png

首先分析下它的结构。

一个列表里,有Image、Text,他们是横向HStack排布。

我们先在Assets.xcassets导入我们所需的图片。

199.png

200.png

并且我们已经提前给图片命好名了,方便我们接下来使用它们。

我们回到ContentView.swift文件中,创建2个数组,存放我们的图片和文字。

//定义数组,存放数据

var myImages = ["weixin","weibo","qq","phone","mail"]
var myNames = ["这是微信","这是微博","这是QQ","这是电话","这是邮箱"]
复制代码

208.png

我们看到报错了,但又没有完全报错。

这是因为我们定义了一个动态数组,但在代码中没有用到,所以系统告诉我们定义的数组名称没有被使用罢了。

没事的,我们继续。

我们在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])
            }
        }
    }
}
复制代码

209.png

我们还是构建了一个列表,不过使用myImages作为目录,也就是myImages.indices。

然后图片遍历用myImages数组,文字遍历用myNames数组。

是不是很简单,比起以前用UIKit的时候,要给cell协议和声明,SwiftUI几行代码就搞定了。

第三部分:列表数据整合

下面,我们再进阶一下。

上面的代码中,我们发现如果是图片+文字,那么我们创建了2个数组,如果是更加复杂的场景,我们岂不是要建立一堆的数组数据?

不不不,这肯定不够优雅。

最好的方式应该是,无论我们多少数组数据,我们都用一个数组包裹住。

我们回到UI稿中。

207.png 有没有办法,把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)
    }
}
复制代码

那么,最终的结果和我们之前做的效果是一样的。

唯一不一样的是,我们的代码看起来优雅多了。

210.png

小结一下:

我们创建了一个结构体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")
]
复制代码

211.png

我们发现,如果我们使用image作为id,也就是唯一标识符的话。

如果我的数组里有2个image,如果它们的值相同,那么SwiftUI会认为这两个是同一个东西。

也就是,我都是图片都是“微信”,但名称不一样,但计算机认为两个都是微信,而且值一样,这是因为image作为id是唯一的。

这时候,我们该怎么办?

我们期望的结果是,Messages数组里,每一个结构体的数据都是唯一的。

那么我们就不能在body构建唯一的标识符,应该在传值之前就在Message结构体里构建唯一的id。

struct Message {
    var id = UUID()
    var image: String
    var name: String
}
复制代码

En el código, agregamos la propiedad id y la inicializamos con un identificador único.

La función UUID() se utiliza para generar un identificador aleatorio global único.

Los UUID se componen de números de 128 bits, por lo que, en teoría, la posibilidad de tener dos identificadores idénticos es prácticamente nula.

Luego, usamos la identificación en el código del cuerpo para referirnos a la identificación de la estructura del mensaje.

// 列表

List(Messages, id: \.id) { Message in
    HStack {
        Image(Message.image)
            .resizable()
            .frame(width: 40, height: 40)
            .cornerRadius(5)
    Text(Message.name)
    }
}
复制代码

De esta forma, hemos completado la unicidad de la fuente de datos Lista.

212.png

Un punto más de conocimiento.

También podemos configurar la estructura Mensaje para seguir el protocolo Identificable.

De esta forma, una estructura que se ajusta a Identificable puede rastrear automáticamente su id como un identificador único, y no necesitamos especificar una id en el cuerpo.

El código completo es el siguiente:

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
}
复制代码

213.png

¡Felicidades! ¡Completado el aprendizaje de List!

Si esta columna es útil para usted, haga clic en Me gusta, comente y siga ~

Supongo que te gusta

Origin juejin.im/post/7085515068586065950
Recomendado
Clasificación