I have followed this stackoverflow answer to bridge a custom DayViewController with a SwiftUI view. And it is all working great. Except, when I need to create a new event I open up a .sheet()
to let the users edit the event. (I have a custom struct that holds other details about the event, although in the initialization of the DayViewController I manually turn these structs into an Event for the DayViewController).
Hence, because the user can edit the event. I don't want to add it to the events list until they are done editing the info in the sheet in SwiftUI.
But I can't figure out how to add an event once the editing is done since the editing is done in SwiftUI and I need to create the Event through the create() func in the DayViewController
CustomDayViewController-
import UIKit
import CalendarKit
class CalendarController: DayViewController {
convenience init(newVM: AvailabilityViewModel){
self.init()
self.availabilityViewModel = newVM
}
var availabilityViewModel = AvailabilityViewModel(newMapper: APIMapper(), newUser: User(id: 0, first_name: "test", last_name: "man", username: "testman", email: "test@test.com", user_password: "test123"))
var generatedEvents = [EventDescriptor]()
var alreadyGeneratedSet = Set<Date>()
var colors = [UIColor.blue,
UIColor.yellow,
UIColor.green,
UIColor.red]
private lazy var rangeFormatter: DateIntervalFormatter = {
let fmt = DateIntervalFormatter()
fmt.dateStyle = .none
fmt.timeStyle = .short
return fmt
}()
override func loadView() {
calendar.timeZone = TimeZone(identifier: "MST")!
dayView = DayView(calendar: calendar)
view = dayView
}
override func viewDidLoad() {
super.viewDidLoad()
title = "CalendarKit Demo"
navigationController?.navigationBar.isTranslucent = false
dayView.autoScrollToFirstEvent = true
reloadData()
}
// MARK: EventDataSource
override func eventsForDate(_ date: Date) -> [EventDescriptor] {
var events = [Event]()
while availabilityViewModel.dataLoaded == false {
}
if let availabilities = availabilityViewModel.timeslots[date] {
for availability in availabilities {
let event = Event()
event.startDate = availability.start_time
event.endDate = availability.end_time
event.text = availability.availability_type
event.color = getColorForType(availability.availability_type)
events.append(event)
}
}
return events
}
private func getColorForType(_ availability: String) -> UIColor {
if availability == "preferred"{
return UIColor.green
}
else if availability == "maybe" {
return UIColor.yellow
}
else {
return UIColor.red
}
}
private func textColorForEventInDarkTheme(baseColor: UIColor) -> UIColor {
var h: CGFloat = 0, s: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0
baseColor.getHue(&h, saturation: &s, brightness: &b, alpha: &a)
return UIColor(hue: h, saturation: s * 0.3, brightness: b, alpha: a)
}
// MARK: DayViewDelegate
private var createdEvent: EventDescriptor?
override func dayViewDidSelectEventView(_ eventView: EventView) {
guard let descriptor = eventView.descriptor as? Event else {
return
}
print("Event has been selected: \(descriptor) \(String(describing: descriptor.userInfo))")
}
override func dayViewDidBeginDragging(dayView: DayView) {
endEventEditing()
print("DayView did begin dragging")
}
override func dayView(dayView: DayView, willMoveTo date: Date) {
print("DayView = \(dayView) will move to: \(date)")
}
override func dayView(dayView: DayView, didMoveTo date: Date) {
print("DayView = \(dayView) did move to: \(date)")
}
override func dayView(dayView: DayView, didLongPressTimelineAt date: Date) {
// Cancel editing current event and start creating a new one
endEventEditing()
availabilityViewModel.StartNewAvailability(startDate: MoveTimeToNearestHalfHour(dateToMove: date))
availabilityViewModel.ShowDateEditor()
}
private func MoveTimeToNearestHalfHour(dateToMove: Date) -> Date {
//convert to DateComponent
let calendar = Calendar.current
var components = calendar.dateComponents([Calendar.Component.year, Calendar.Component.month, Calendar.Component.day,Calendar.Component.hour, Calendar.Component.minute], from: dateToMove)
if components.minute! < 30 {
components.minute = 0
}
else {
components.minute = 30
}
return calendar.date(from: components) ?? dateToMove
}
override func dayView(dayView: DayView, didUpdate event: EventDescriptor) {
print("did finish editing \(event)")
print("new startDate: \(event.startDate) new endDate: \(event.endDate)")
}
}
BridgerController
import SwiftUI
import UIKit
struct BridgerController: UIViewControllerRepresentable {
@ObservedObject var availabilityViewModel: AvailabilityViewModel
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
}
func makeUIViewController(context: Context) -> some UIViewController {
let dayViewController = CalendarController(newVM:availabilityViewModel)
return dayViewController
}
}
I've tried creating a override of the create function in my Custom DayViewController. But, I have no way to access it from SwiftUI.
Any help would be appreciated!