译自 www.hackingwithswift.com/books/ios-s…
更多内容,欢迎关注公众号 「Swift花园」
喜欢文章?不如来个 🔺💛➕三连?关注专栏,关注我 🚀🚀🚀
动态过滤 SwiftUI 列表
对于 SwiftUI 的 List
视图,配合使用的对象最好遵循 Identifiable
协议,或者你至少需要提供某个 id
参数,确保元素对应的字段是唯一的。
在我们的应用中,有三个 ProspectsView
实例,它们根据传入的 FilterType
属性的不同呈现不同的内容。我们已经用这个属性来设置不同的标签,现在要再利用它来设置 List
的内容。
最简单的做法是使用 Swift 的 filter()
方法。这个方法会遍历序列中每个元素,执行你以闭包提供的一个测试,只有测试通过,元素才会被放入新数组返回。我们的 ProspectsView
已经有 prospects
属性,里面包含一个 people 的数组。我们既可以返回所有 people,也可以返回所有联络过的 people,又或者是所有未联络过的 people。
把下面这个属性添加到 ProspectsView
:
var filteredProspects: [Prospect] {
switch filter {
case .none:
return prospects.people
case .contacted:
return prospects.people.filter { $0.isContacted }
case .uncontacted:
return prospects.people.filter { !$0.isContacted }
}
}
当 filter()
执行时,它会把 people
数组里的每个元素都传给我们的测试。因此, $0.isContacted
代表 “当前元素的 isContacted
property 是否为 true
?” 所有通过测试的项 —— 即 isContacted
是 true 的项 —— 都会被添加到一个新数组,并从 filteredResults
返回。而当我们使用 !$0.isContacted
时,可以得到相反的结果:只有没有被联络过的 prospect 会被包含。
有了上面这个计算属性,我们就可以创建一个遍历该数组的 List
。列表用 VStack
显示了每个 prospect 的标题和邮件地址。也为了能够删除项,我们会采用 ForEach
。
把 ProspectsView
里的文本视图替换为下面的代码:
List {
ForEach(filteredProspects) { prospect in
VStack(alignment: .leading) {
Text(prospect.name)
.font(.headline)
Text(prospect.emailAddress)
.foregroundColor(.secondary)
}
}
}
再次运行应用,你可以看到,应用外观看起来好多了。
在我们继续之前,我希望你思考一个问题:既然我们采用了计算属性,但属性变化时 SwiftUI 要如何刷新视图?答案很简单:刷新不由计算属性触发。
当我们添加一个 @EnvironmentObject
属性到 ProspectsView
时,我们其实也是在要求每当该属性变化时 SwiftUI 重新调用 body
属性。因此,每当我们插入一个新的人到 people
数组时,它的 @Published
属性包装器会自动告诉所有观察它的视图,而 SwiftUI 则会重新调用 ProspectsView
的 body
属性。这反过来又会重新计算该属性,这样 List
就变了。
我喜欢 SwiftUI 显而易见地处理大量工作的方式,这让我们可以聚焦在过滤和呈现数据,而不用关心如何连接各种管道,以便东西能保持最新。
我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~