SwiftUI中如何将Firebase获取的单元素会议数组转为单个对象
问题与解答
场景背景
我通过Firebase Firestore获取会议列表,按timestamp升序排列,设置limit=1时会返回仅包含一个会议元素的数组。我希望将这个单元素数组转换为单个Optional类型的Meeting对象upcomingmeeting以便直接使用,于是在ViewModel中为数组添加didSet监听,将数组第一个元素赋值给upcomingmeeting。期间因View中错误调用属性名导致报错,修正后问题解决,但不清楚测试代码viewModel.meetings1.append(Meeting(title: "meeting-1"))的作用。
相关代码片段
1. Firestore会议数据获取逻辑
@MainActor static func fetchMeeting(limit: Int? = nil) async throws -> [Meeting] { let snapshot = try await FirestoreConstants.MeetingsCollection.getDocuments() let query = FirestoreConstants.MeetingsCollection.order(by: "timestamp", descending: false) if let limit { let snapshot = try await query.limit(to: limit).getDocuments() return mapMeeting(fromSnapshot: snapshot) } return snapshot.documents.compactMap({ try? $0.data(as: Meeting.self) }) } private static func mapMeeting(fromSnapshot snapshot: QuerySnapshot) -> [Meeting] { return snapshot.documents .compactMap({ try? $0.data(as: Meeting.self) }) }
2. ViewModel实现
class MeetingViewModel: ObservableObject{ init(){ Task{ try await fetchAllMeetings() } Task{ try await fetchMeeting()} } private let fetchLimit = 1 @Published var upcomingmeeting: Meeting? @Published var meetings1 = [Meeting]() { didSet { if let first = meetings1.first { upcomingmeeting = first } } } // 供用户主屏幕展示使用 @MainActor func fetchMeeting() async throws { self.meetings1 = try await MeetingService.fetchMeeting(limit: fetchLimit) } }
3. Meeting模型定义
struct Meeting: Codable, Identifiable, Hashable { @DocumentID var id: String? let uid: String let address: String let citystate: String let hostsite: String let title: String let timestamp: Timestamp }
测试代码作用解答
viewModel.meetings1.append(Meeting(title: "meeting-1"))是用来快速验证ViewModel中监听逻辑的有效性,具体作用如下:
- 手动向
meetings1数组添加测试数据,触发数组的didSet回调 - 验证
didSet中的逻辑是否能正确将数组第一个元素赋值给upcomingmeeting - 无需依赖Firestore网络请求,就能测试
upcomingmeeting是否会随着meetings1的更新同步变化,同时可以验证UI是否能响应upcomingmeeting的变更(比如显示测试会议的标题)
内容的提问来源于stack exchange,提问作者johnny
相关产品推荐
相关产品推荐

