You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将会议ID从View传入ViewModel以查询Firebase子集合

解决方案:将会议ID传入ViewModel查询Firebase子集合

针对你遇到的问题,核心是把已获取的meetingId传递给ViewModel,用于查询对应子集合数据。下面提供两种直接可行的实现方案:

方案一:初始化ViewModel时传入会议ID

这种方式最直接,在创建ViewModel时就把会议ID注入,ViewModel可以立即开始获取子集合数据。

1. 修改MeetingViewModel,添加带参数的初始化方法

class MeetingViewModel: ObservableObject {
    @Published var breakouts: [Breakout] = []
    @Published var tours: [Tour] = []
    private var currentMeetingId: String?

    // 支持传入会议ID的初始化方法
    init(meetingId: String? = nil) {
        self.currentMeetingId = meetingId
        // 如果有会议ID,初始化时自动拉取子集合数据
        if let id = meetingId {
            Task { try await fetchSubCollections(for: id) }
        }
    }

    // 拉取指定会议的子集合数据
    func fetchSubCollections(for meetingId: String) async throws {
        // 查询breakouts子集合
        let breakoutsSnapshot = try await Firestore.firestore()
            .collection("meetings")
            .document(meetingId)
            .collection("breakouts")
            .getDocuments()
        self.breakouts = breakoutsSnapshot.documents.compactMap { try? $0.data(as: Breakout.self) }

        // 查询tours子集合
        let toursSnapshot = try await Firestore.firestore()
            .collection("meetings")
            .document(meetingId)
            .collection("tours")
            .getDocuments()
        self.tours = toursSnapshot.documents.compactMap { try? $0.data(as: Tour.self) }
    }

    // 保留原有fetchAllMeetings方法
    func fetchAllMeetings() async throws {
        // ... 原有逻辑
    }
}

2. 修改目标视图LongProductsView,传入会议ID初始化ViewModel

struct LongProductsView: View {
    @StateObject var viewModel: MeetingViewModel
    @State private var showNewMeetingView = false
    @State private var showMeeting = false
    @Environment(\.dismiss) var dismiss

    var meet: Meeting

    // 自定义初始化方法,接收会议对象并传入ViewModel
    init(meet: Meeting) {
        self.meet = meet
        self._viewModel = StateObject(wrappedValue: MeetingViewModel(meetingId: meet.id))
    }

    var body: some View {
        VStack {
            Text(meet.title)
            Text(meet.datestart)
            
            // 示例:展示breakouts子集合数据
            List(viewModel.breakouts) { breakout in
                Text(breakout.name)
            }
        }
        .toolbar{
            ToolbarItem(placement: .navigationBarLeading) {
                Button(action: { dismiss() }) {
                    Image(systemName: "arrowshape.turn.up.backward")
                        .font(.footnote)
                        .foregroundColor(.blue)
                }
                .padding(.vertical)
            }
        }
    }
}

方案二:在视图出现时传递会议ID给ViewModel

如果不想修改ViewModel的初始化逻辑,可以在视图onAppear时调用ViewModel的方法,传入会议ID并触发数据拉取。

1. 修改MeetingViewModel,添加设置会议ID并拉取数据的方法

class MeetingViewModel: ObservableObject {
    @Published var breakouts: [Breakout] = []
    @Published var tours: [Tour] = []
    private var currentMeetingId: String?

    // 设置会议ID并拉取对应子集合数据
    func setMeetingAndFetchData(_ meetingId: String) async throws {
        // 避免重复请求同一会议的数据
        guard currentMeetingId != meetingId else { return }
        currentMeetingId = meetingId
        
        try await fetchBreakouts(for: meetingId)
        try await fetchTours(for: meetingId)
    }

    private func fetchBreakouts(for meetingId: String) async throws {
        let snapshot = try await Firestore.firestore()
            .collection("meetings")
            .document(meetingId)
            .collection("breakouts")
            .getDocuments()
        self.breakouts = snapshot.documents.compactMap { try? $0.data(as: Breakout.self) }
    }

    private func fetchTours(for meetingId: String) async throws {
        let snapshot = try await Firestore.firestore()
            .collection("meetings")
            .document(meetingId)
            .collection("tours")
            .getDocuments()
        self.tours = snapshot.documents.compactMap { try? $0.data(as: Tour.self) }
    }

    // 保留原有fetchAllMeetings方法
    func fetchAllMeetings() async throws {
        // ... 原有逻辑
    }
}

2. 修改目标视图,在onAppear时调用方法

struct LongProductsView: View {
    @StateObject var viewModel = MeetingViewModel()
    @State private var showNewMeetingView = false
    @State private var showMeeting = false
    @Environment(\.dismiss) var dismiss

    var meet: Meeting

    var body: some View {
        VStack {
            Text(meet.title)
            Text(meet.datestart)
            
            List(viewModel.breakouts) { breakout in
                Text(breakout.name)
            }
        }
        .toolbar{
            ToolbarItem(placement: .navigationBarLeading) {
                Button(action: { dismiss() }) {
                    Image(systemName: "arrowshape.turn.up.backward")
                        .font(.footnote)
                        .foregroundColor(.blue)
                }
                .padding(.vertical)
            }
        }
        .onAppear {
            Task {
                try await viewModel.setMeetingAndFetchData(meet.id)
            }
        }
    }
}

额外注意事项

  • 如果需要实时监听子集合数据变化,可以将getDocuments()替换为addSnapshotListener,实现数据实时同步
  • 建议在ViewModel中添加@Published var error: Error?属性,用于捕获并在视图中展示异步请求的错误
  • 确保Firebase的安全规则允许当前用户访问指定会议的子集合数据

内容的提问来源于stack exchange,提问作者johnny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:34:57