首页 > 解决方案 > SwiftUI+Firestore 中的多选列表

问题描述

我正在尝试从 Firestore 加载集合列表,并让它们可以单独选择。我将它设置在从 Firestore 中拉入列表的位置,但如果我选择一个,它会选择全部。另外,我如何将这个数组拉到按钮的 VStack 中而不是列表中?在我的选择屏幕中,此列表有点位于页面中间,我宁愿使用按钮而不是列表,因为列表组件的大小不是动态的。

感谢您的帮助,代码如下!

import SwiftUI

struct FirestoreTest: View {
    
    @ObservedObject private var viewModel = TriggersViewModel()
    @State private var isSelected = false
    
    var body: some View {
        
        List(viewModel.triggers) { trigger in
            Button(action: { self.isSelected.toggle() }) {
                HStack {
                    if self.isSelected {
                    Text(trigger.name)
                        .foregroundColor(.white)
                        .font(.system(size: 16, weight: .bold))

                        Spacer()
                        Image(systemName: "checkmark")
                            .foregroundColor(Color(.systemPink))
                            .font(.system(size: 16))
                    } else {
                        Text(trigger.name)
                            .foregroundColor(Color(.systemGray))
                            .font(.system(size: 16))
                    }
                }
                .padding(.vertical, 10)
            }
        }
        .onAppear() {
            self.viewModel.fetchData()
        }
        
    }
}

TriggerViewModel.swift

import SwiftUI
import FirebaseFirestore

class TriggersViewModel: ObservableObject {
    
    @Published var triggers = [Trigger]()
    
    private var db = Firestore.firestore()
    
    func fetchData() {
        db.collection("triggers").order(by: "name").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No Documents")
                return
            }
            
                self.triggers = documents.map { (queryDocumentSnapshot) -> Trigger in
                let data = queryDocumentSnapshot.data()
                
                let name = data["name"] as? String ?? ""
                
                return Trigger(name: name)
                
            }
            
        }
    }
}

触发器.swift

import SwiftUI

struct Trigger: Identifiable {
    var id: String = UUID().uuidString
    var name: String
}

标签: iosswiftfirebasegoogle-cloud-firestoreswiftui

解决方案


您需要isSelected进入模型并使用ForEachfor VStack

这是可能的解决方案:

struct Trigger: Identifiable {
    var id: String = UUID().uuidString
    var name: String
    var isSelected = false
}

现在您可以删除@State private var isSelected = false, 和

VStack {
    ForEach(viewModel.triggers.indices, id: \.self) { i in
        Button(action: { viewModel.triggers[i].isSelected.toggle() }) {
            HStack {
                if viewModel.triggers[i].isSelected {
                Text(viewModel.triggers[i].name)
                    .foregroundColor(.white)
                    .font(.system(size: 16, weight: .bold))

                    Spacer()
                    Image(systemName: "checkmark")
                        .foregroundColor(Color(.systemPink))
                        .font(.system(size: 16))
                } else {
                    Text(viewModel.triggers[i].name)
                        .foregroundColor(Color(.systemGray))
                        .font(.system(size: 16))
                }
            }
            .padding(.vertical, 10)
        }
    }
}

推荐阅读