前言
今日鸡汤:没有鸡汤!
今日我们学习 SwiftUI 中比较重要的视图构造器 ForEach
. 这个其实有些类似我们在 Swift
中处理自己集合逻辑中遍历集合对象的 forEach
运算符.
其实这两个概念上很相似,只不过 他们在应用的范围上有些区别. ForEach
是视图构造器,它允许我们在用户界面中动态生成多个类型相同的视图,它允许你根据某个数据集合,重复创建视图,并且保持其性能高效。
而 forEach 是 Swift
中循环 遍历的一种方式,类似于 for...in
,但是它相对 for...in
更加注重 函数方式的编程.
好的,我们开始我们本章的学习.
正文
虽然这一步很繁琐,但是这样我觉得可以帮助我们更加系统的归纳我们学习的过程;我们进入我们的工程项目点击Xcode顶部导航的 File > New > File from Template 选择 iOS > SwiftUI 模版创建新的SwiftUI文件。
快捷键 Command + N
,我们新建文件名为 ForEachBootcamp.swift
。
首先我们先了解下 ForEach
在 SwiftUI
中的基础用法.
swift
ForEach(data, id: \.self) { item in
// 创建视图
}
data:
是一个数据集合,通常是数组、字典、范围(Range
)等。id: \.self
:用于标识每个视图的唯一性,通常当数据类型是简单类型时(如整型或字符串),可以直接用\.self
, 也就是表示自身作为唯一标识。对于自定义数据类型,通常你需要指定一个唯一属性(如id
)来保证视图的唯一性。item:ForEach
会遍历每一个数据,并为每个数据创建视图。
现在我们开始基础应用的学习, 我们首先在我们代码中定义常量数组 data
, 方便我们进行遍历!
swift
let data: [String] = ["Samul", "Alice", "Bob", "Marry"]
我们开始在主体中应用我们循环视图构造器,我们在视图中新增如下代码:
swift
VStack {
ForEach(data) { item in
Text("\(item)")
}
}
你会发现,我们代码出现这个错误提示: Cannot convert value of type '[String]' to expected argument type 'Range<Int>'
这个主要原因是 ForEach
的初始化方法有不同的重载形式,我们目前使用的版本要求传入一个整数范围(Range<Int>
),但是你传入的是一个数组 [String]
。我们有两种办法去进行修复.
- 添加唯一标识符
id
swift
VStack {
ForEach(data, id: \.self) { item in
Text("\(item)")
}
}
- 将我们传入的数据转换为符合类型的
Rang<Int>
:
我们主要是通过访问集合的内置属性.indices
,它会返回该集合的所有有效的索引,我们可以将其作为我们遍历的对象。
swift
ForEach(data.indices) { index in
Text("\(index)")
}
你可以看到目前我们遍历出当前的 data
集合对象的索引集,但是我们的目的是显示 data
数据集,我们可以这样访问然后显示数据。
我们通过 data[index]
访问当前索引的数据就 OK!
问题还没有解决,我们目前还有提示错误:Non-constant range: not an integer range
这个错误提示通常表示你在 ForEach
中传入了一个不合法的范围(非整数范围),或者尝试使用了一个动态的或不确定的范围。在 SwiftUI
中,ForEach
需要一个稳定的集合或范围,它可以追踪和唯一标识每个元素。如果遇到了 Non-constant range
的错误,通常是由于使用了不正确的范围值或集合.
所以为了修复目前的问题,我们可以添加唯一标识符 id, 确保唯一标识符号的稳定性.
问题就解决了!
为什么需要标识了,主要原因是 SwiftUI 是声明形式的框架,它需要通过数据驱动的方式进行管理 UI,当数据变动的时候自动更新相关的视图,为了保证数据变化时视图能够正确的更新,SwiftUI 需要为每个数据对象分配唯一的标识。
当使用 ForEach 遍历对象时,SwiftUI 需要知道每个对象的唯一性,以便:
-
区分每个视图:如果没有唯一标识符,SwiftUI 将不知道如何区分每个对象,无法确保视图的一一对应。
-
高效更新:SwiftUI 可以根据唯一标识符来追踪哪些视图需要更新、添加或删除。这样它只会重新渲染受影响的视图,而不是整个列表,从而优化性能。
所以在 我们使用视图构造器的时候保持良好的代码编写习惯,显式的方式标识
id
.
好的!
关于 ForEach 的概念以及基本使用介绍到这!希望对你有帮助!下章再见👋!