[SwiftUI 100 天] 动态过滤 SwiftUI 列表

1,215 阅读2分钟

译自 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 代表 “当前元素的 isContactedproperty 是否为 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 则会重新调用 ProspectsViewbody 属性。这反过来又会重新计算该属性,这样 List 就变了。

我喜欢 SwiftUI 显而易见地处理大量工作的方式,这让我们可以聚焦在过滤和呈现数据,而不用关心如何连接各种管道,以便东西能保持最新。


我的公众号 这里有Swift及计算机编程的相关文章,以及优秀国外文章翻译,欢迎关注~

Swift花园微信公众号