How to use EKCalendarChooser with SwiftUI
Short post showing how to bridge this controller with SwiftUI and get selected calendars.
Just like other UIKit controllers EKCalendarChooser
which lets users select their calendars in use in your app needs a small wrapper around it with the UIViewControllerRepresentable
protocol.
This code below is intended as a starting point for folks who need to work with EKCalendarChooser
in their SwiftUI project.
Big thanks to Paul Hudson for this guide about using UIImagePickerController
with SwiftUI which served as an inspiration.
So here is the code:
import SwiftUI
import EventKitUI
struct CalendarChooser: UIViewControllerRepresentable {
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
@Environment(\.presentationMode) var presentationMode
@Binding var calendars: Set<EKCalendar>?
let eventStore: EKEventStore
func makeUIViewController(context: UIViewControllerRepresentableContext<CalendarChooser>) -> UINavigationController {
let chooser = EKCalendarChooser(selectionStyle: .multiple, displayStyle: .allCalendars, entityType: .event, eventStore: eventStore)
chooser.selectedCalendars = calendars ?? []
chooser.delegate = context.coordinator
chooser.showsDoneButton = true
chooser.showsCancelButton = true
return UINavigationController(rootViewController: chooser)
}
func updateUIViewController(_ uiViewController: UINavigationController, context: UIViewControllerRepresentableContext<CalendarChooser>) {
}
class Coordinator: NSObject, UINavigationControllerDelegate, EKCalendarChooserDelegate {
let parent: CalendarChooser
init(_ parent: CalendarChooser) {
self.parent = parent
}
func calendarChooserDidFinish(_ calendarChooser: EKCalendarChooser) {
parent.calendars = calendarChooser.selectedCalendars
parent.presentationMode.wrappedValue.dismiss()
}
func calendarChooserDidCancel(_ calendarChooser: EKCalendarChooser) {
parent.presentationMode.wrappedValue.dismiss()
}
}
}
Sample usage can look something like this:
.sheet(isPresented: $showingCalendarChooser) {
CalendarChooser(calendars: self.$eventsRepository.selectedCalendars, eventStore: self.eventsRepository.eventStore)
}
You need to pass in Binding
for selected calendars and also instance of EKEventStore
.
I am using this definition for selectedCalendars
:
@Published var selectedCalendars: Set<EKCalendar>?
For more on EventKit check out other posts in this series or my example project on GitHub.
Uses: Xcode 11 & Swift 5
Follow me on Twitter for latest updates and news