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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:40:24