ios – I’m looking to integrate CalendarKit library with SwiftUI Representable, facing issue with data handling


I’m attempting to implement CalendarKit using SwiftUI’s UIViewControllerRepresentable. The example provided by the library is in UIKit. I’ve successfully displayed the UI, but when I try to pass dummy events data to display events in CalendarKit, the DayViewDelegate and EventDataSource methods inside the coordinator class are not being called, and no data is being displayed.
What am I doing wrong, or how can I achieve this? Any kind of help would be appreciated.

My SwiftUI Representable Code:

import SwiftUI
import CalendarKit


struct DayViewControllerWrapper: UIViewControllerRepresentable {
    
    @Binding var selectedEvent: Event?
    @Binding var events: [EventDescriptor]
    
    // Callbacks for coordinator delegates
    var didSelectEventView: ((EventView) -> Void)?
    var didLongPressEventView: ((EventView) -> Void)?
    var didTapTimelineAt: ((Date) -> Void)?
    var didLongPressTimelineAt: ((Date) -> Void)?
    var didBeginDragging: (() -> Void)?
    var didTransitionCancel: (() -> Void)?
    var willMoveTo: ((Date) -> Void)?
    var didMoveTo: ((Date) -> Void)?
    var didUpdateEvent: ((EventDescriptor) -> Void)?
    
    func makeUIViewController(context: Context) -> DayViewController {
        let viewController = DayViewController()
        
        // Set up bindings for delegates and data sources
        viewController.dataSource = context.coordinator
        viewController.delegate = context.coordinator
        
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: DayViewController, context: Context) {
        
        uiViewController.reloadData()
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }
    
    class Coordinator: NSObject, EventDataSource, DayViewDelegate {
        
        var parent: DayViewControllerWrapper
        
        init(_ parent: DayViewControllerWrapper) {
            self.parent = parent
        }
        
        // MARK: - EventDataSource
        
        func eventsForDate(_ date: Date) -> [EventDescriptor] {
            return parent.events
        }
        
        // MARK: - DayViewDelegate
        
        func dayViewDidSelectEventView(_ eventView: EventView) {
            parent.selectedEvent = eventView.descriptor as? Event
            parent.didSelectEventView?(eventView)
        }
        
        func dayViewDidLongPressEventView(_ eventView: EventView) {
            parent.didLongPressEventView?(eventView)
        }
        
        func dayView(dayView: DayView, didTapTimelineAt date: Date) {
            parent.didTapTimelineAt?(date)
        }
        
        func dayView(dayView: DayView, didLongPressTimelineAt date: Date) {
            parent.didLongPressTimelineAt?(date)
        }
        
        func dayViewDidBeginDragging(dayView: DayView) {
            parent.didBeginDragging?()
        }
        
        func dayViewDidTransitionCancel(dayView: DayView) {
            parent.didTransitionCancel?()
        }
        
        func dayView(dayView: DayView, willMoveTo date: Date) {
            parent.willMoveTo?(date)
        }
        
        func dayView(dayView: DayView, didMoveTo date: Date) {
            parent.didMoveTo?(date)
        }
        
        func dayView(dayView: DayView, didUpdate event: EventDescriptor) {
            parent.didUpdateEvent?(event)
        }
    }
}

struct DayViewControllerWrapper_Previews: PreviewProvider {
    static var previews: some View {
        DayViewControllerWrapper(selectedEvent: .constant(nil), events: .constant([]))
    }
}

My ContentView code, how i’m using it.

import SwiftUI
import CalendarKit

struct ContentView: View {
    
    @State private var selectedEvent: Event?
    @State private var events: [EventDescriptor] = []
    
    var body: some View {
        VStack {
            Text("My Custom Calendar Example")
            DayViewControllerWrapper(
                selectedEvent: $selectedEvent,
                events: $events,
                didSelectEventView: { eventView in
                    // Handle event selection
                    print("Selected event: \(eventView.descriptor)")
                },
                didLongPressEventView: { eventView in
                    // Handle long press event
                    print("Long pressed event: \(eventView.descriptor)")
                },
                didTapTimelineAt: { date in
                    // Handle tap on timeline
                    print("Tapped timeline at: \(date)")
                },
                didLongPressTimelineAt: { date in
                    // Handle long press on timeline
                    print("Long pressed timeline at: \(date)")
                },
                didBeginDragging: {
                    // Handle begin dragging
                    print("Began dragging")
                },
                didTransitionCancel: {
                    // Handle transition cancel
                    print("Transition canceled")
                },
                willMoveTo: { date in
                    // Handle will move to date
                    print("Will move to date: \(date)")
                },
                didMoveTo: { date in
                    // Handle did move to date
                    print("Did move to date: \(date)")
                },
                didUpdateEvent: { event in
                    // Handle updating event
                    print("Updated event: \(event)")
                }
            )
            .frame(height: 400) // Adjust frame height as needed
            .onAppear {
                // Populate events with dummy data
                generateDummyData()
            }
        }
    }
    
    private func generateDummyData() {
        events = [
            createEvent(title: "Breakfast at Tiffany's", location: "New York, 5th avenue"),
            createEvent(title: "Workout", location: "Tufteparken"),
            createEvent(title: "Meeting with Alex", location: "Home, Oslo, Tjuvholmen"),
            createEvent(title: "Beach Volleyball", location: "Ipanema Beach, Rio De Janeiro"),
            createEvent(title: "WWDC", location: "Moscone West Convention Center, 747 Howard St"),
            createEvent(title: "Google I/O", location: "Shoreline Amphitheatre, One Amphitheatre Parkway"),
            createEvent(title: "✈️️ to Svalbard ❄️️❄️️❄️️❤️️", location: "Oslo Gardermoen"),
            createEvent(title: "💻📲 Developing CalendarKit", location: "🌍 Worldwide"),
            createEvent(title: "Software Development Lecture", location: "Mikpoli MB310, Craig Federighi")
        ]
    }
    
    private func createEvent(title: String, location: String) -> EventDescriptor {
        let event = Event()
        event.startDate = Date()
        event.endDate = Date().addingTimeInterval(3600)
        event.text = "\(title)\n\(location)"
        event.color = .blue
        event.isAllDay = false
        event.userInfo = nil
        return event
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Library provided UIKit example code:
https://github.com/richardtop/CalendarKit/blob/master/CalendarKitDemo/CalendarApp/CustomCalendarExampleController.swift

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img