如何在SwiftUI中借助Cloud Firebase统计指定区域的选项选择人数?
解决指定区域内情绪选择人数统计的问题
看起来你已经完成了基础的数据存储部分,接下来只需要几个关键步骤就能实现区域内的人数统计,我来一步步帮你梳理:
1. 完善数据模型,添加情绪记录字段
你的Lokasyon结构体目前缺少记录用户选择"good"/"bad"的字段,首先要补上这个信息。推荐用枚举类型约束可选值,避免字符串拼写错误:
// 定义情绪枚举,符合Codable以便和Firestore交互 enum UserFeeling: String, Codable { case good, bad } struct Lokasyon: Identifiable, Codable { var id : String var cityName: String var districtName: String var okeyButton : Bool var feeling: UserFeeling // 新增:记录用户选择的情绪 }
注意:要确保用户在FirstView选择"good"/"bad"后,提交数据到Firestore时,这个feeling字段已经被正确写入文档中。
2. 传递用户选中的区域到ThirdView
ThirdView需要明确要统计哪个区域的数据,所以要从SecondView把用户选择的cityName和districtName传递过来。修改ThirdView的定义,添加接收参数:
struct ThirdView: View { @ObservedObject var viewModel = TakeViewModel() // 接收从SecondView传递来的选中区域 let selectedCity: String let selectedDistrict: String // ... 其他代码 }
比如从SecondView跳转时可以这样传值:
NavigationLink(destination: ThirdView(selectedCity: selectedCity, selectedDistrict: selectedDistrict)) { Text("查看统计") }
3. 实现区域内的人数统计逻辑
添加计算属性,过滤出指定区域内对应情绪的记录并统计数量:
struct ThirdView: View { @ObservedObject var viewModel = TakeViewModel() let selectedCity: String let selectedDistrict: String // 统计当前区域选择"good"的人数 private var goodCount: Int { viewModel.lokasyon.filter { item in item.cityName == selectedCity && item.districtName == selectedDistrict && item.feeling == .good }.count } // 统计当前区域选择"bad"的人数 private var badCount: Int { viewModel.lokasyon.filter { item in item.cityName == selectedCity && item.districtName == selectedDistrict && item.feeling == .bad }.count } var body: some View { VStack{ VStack(spacing: 25){ Text("How others feel in") // 显示用户选中的区域,而非遍历所有数据 VStack{ Text(selectedCity) Text(selectedDistrict) } HStack{ VStack{ Image("smile") .resizable() .aspectRatio(contentMode: .fit) Text("\(goodCount)") // 替换手动数字为统计结果 Text("Feeling Good") } VStack{ Image("sad") .resizable() .aspectRatio(contentMode: .fit) Text("\(badCount)") // 替换手动数字为统计结果 Text("Feeling Bad") } } } }.onAppear(perform: viewModel.subscribe) } }
4. 可选优化:减少客户端数据量(适合大数据场景)
如果Firestore中数据量较大,客户端过滤会比较低效,可以修改subscribe方法,直接在Firestore查询时就过滤指定区域的数据:
class TakeViewModel: ObservableObject { @Published var lokasyon = [Lokasyon]() private var db = Firestore.firestore() private var listenerRegistration: ListenerRegistration? deinit { unsubscribe() } func unsubscribe() { listenerRegistration?.remove() listenerRegistration = nil } // 修改subscribe方法,接收区域参数做精准查询 func subscribe(forCity city: String, district: String) { unsubscribe() listenerRegistration = db.collection("posts") .whereField("cityName", isEqualTo: city) .whereField("districtName", isEqualTo: district) .addSnapshotListener { (querySnapshot, error) in guard let documents = querySnapshot?.documents else { print("No documents found for this area") return } self.lokasyon = documents.compactMap { try? $0.data(as: Lokasyon.self) } } } }
然后在ThirdView的onAppear里调用优化后的方法:
.onAppear { viewModel.subscribe(forCity: selectedCity, district: selectedDistrict) }
这样ThirdView只会获取当前选中区域的数据,既节省带宽又提升统计效率。
内容的提问来源于stack exchange,提问作者Ozan
相关产品推荐
相关产品推荐

