SwiftUI集成KVKCalendar:UIViewRepresentable的API事件数据刷新方案
解决方案:精准触发日历事件刷新(避免重复API请求)
1. 用ViewModel管控事件状态与刷新时机
给ViewModel添加手动触发的API请求方法,拒绝自动触发的无意义请求,只在明确需要时调用:
class CalendarViewModel: ObservableObject { @Published var events: [KVKEvent] = [] // 仅手动调用时才发起API请求 func fetchEvents() async { do { let fetchedEvents = try await APIService.getEvents() DispatchQueue.main.async { self.events = fetchedEvents } } catch { print("获取事件失败: \(error)") } } }
2. 在CalendarScreen中监听写页面的消失事件
针对不同的页面跳转方式,精准绑定写页面消失的触发逻辑,确保只有从CalendarWriteScreen返回时才刷新:
场景1:NavigationStack跳转
struct CalendarScreen: View { @StateObject private var viewModel = CalendarViewModel() @State private var isWriteScreenPresented = false var body: some View { NavigationStack { CalendarDisplayView(events: viewModel.events) .navigationTitle("日历") .toolbar { Button("添加事件") { isWriteScreenPresented = true } } .navigationDestination(isPresented: $isWriteScreenPresented) { CalendarWriteScreen() .onDisappear { // 仅从写页面返回时触发刷新 Task { await viewModel.fetchEvents() } } } } .onAppear { // 首次进入页面时请求一次数据 Task { await viewModel.fetchEvents() } } } }
场景2:模态Sheet弹窗
struct CalendarScreen: View { @StateObject private var viewModel = CalendarViewModel() @State private var isWriteSheetPresented = false var body: some View { CalendarDisplayView(events: viewModel.events) .toolbar { Button("添加事件") { isWriteSheetPresented = true } } .sheet(isPresented: $isWriteSheetPresented) { // 模态弹窗消失时触发刷新 Task { await viewModel.fetchEvents() } } content: { CalendarWriteScreen() } .onAppear { Task { await viewModel.fetchEvents() } } } }
3. 确保UIViewRepresentable响应数据变化
CalendarDisplayView必须在数据更新时同步刷新KVKCalendar,利用updateUIView方法完成UIKit视图的更新:
struct CalendarDisplayView: UIViewRepresentable { var events: [KVKEvent] func makeUIView(context: Context) -> KVKCalendar { let calendar = KVKCalendar(frame: .zero) calendar.delegate = context.coordinator return calendar } func updateUIView(_ uiView: KVKCalendar, context: Context) { // 数据更新时同步日历事件 uiView.events = events // 强制刷新日历界面 uiView.reloadData() } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, KVKCalendarDelegate { var parent: CalendarDisplayView init(_ parent: CalendarDisplayView) { self.parent = parent } // 实现KVKCalendar所需的代理方法... } }
核心注意事项
- 禁止自动触发API:ViewModel的
fetchEvents必须手动调用,不要用@Published的didSet触发请求,彻底避免无意义的重复请求。 - 精准控制触发时机:仅在CalendarWriteScreen消失时调用刷新,其他场景(如CalendarScreen首次加载)只执行一次请求。
- UIViewRepresentable的更新逻辑:
updateUIView是SwiftUI与UIKit视图同步的核心,必须在这里更新事件并调用reloadData确保界面刷新。
内容的提问来源于stack exchange,提问作者XoliKnight
相关产品推荐
相关产品推荐

