Reputation: 1187
I have an NSObject class that consists of a basic EKCalendarChooser implementation and I am unable to get the delegate functions calendarChooserDidFinish
, calendarChooserSelectionDidChange
, and calendarChooserDidCancel
working. I'm not sure if it is the fact that everything is in an NSObject but I wanted to keep this code separate from my other files.
I've tried a lot of troubleshooting such as not keeping the delegate methods under an extension and even making a global variable for the EKCalendarChooser as I found this post which states that non-global items could be dereferenced in contexts like this. Overall I can get the controller to pop up and it's just the way I want, but the delegate methods don't work. Below is the entire code and in my main viewController I get this to show with AddAppointments(parentViewController: self).chooseCalendarTapped()
import UIKit
import EventKitUI
class Cal: NSObject {
let eventStore = EKEventStore()
var parentViewController: UIViewController
var CalendarChooser: EKCalendarChooser = EKCalendarChooser()
init(parentViewController: UIViewController) {
self.parentViewController = parentViewController
super.init()
}
func chooseCalendarTapped() {
let authStatus = EKEventStore.authorizationStatus(for: .event)
switch authStatus {
case .authorized:
showCalendarChooser()
case .notDetermined:
requestAccess()
case .denied:
// Explain to the user that they did not give permission
break
case .restricted:
break
@unknown default:
preconditionFailure("Who knows what the future holds 🤔")
}
}
func requestAccess() {
eventStore.requestAccess(to: .event) { (granted, error) in
if granted {
// may not be called on the main thread..
DispatchQueue.main.async {
self.showCalendarChooser()
}
}
}
}
func showCalendarChooser() {
CalendarChooser = EKCalendarChooser(selectionStyle: .single, displayStyle: .allCalendars, entityType: .event, eventStore: eventStore)
// customization
CalendarChooser.showsDoneButton = true
CalendarChooser.showsCancelButton = true
// dont forget the delegate
CalendarChooser.delegate = self
let nvc = UINavigationController(rootViewController: CalendarChooser)
parentViewController.present(nvc, animated: true, completion: nil)
}
}
extension Cal : EKCalendarChooserDelegate {
func calendarChooserDidFinish(_ calendarChooser: EKCalendarChooser) {
print(calendarChooser.selectedCalendars)
// dismiss(animated: true, completion: nil)
}
func calendarChooserSelectionDidChange(_ calendarChooser: EKCalendarChooser) {
print("Changed selection")
}
func calendarChooserDidCancel(_ calendarChooser: EKCalendarChooser) {
print("Cancel tapped")
// dismiss(animated: true, completion: nil)
}
}
Upvotes: 0
Views: 120
Reputation: 3750
Check if this works now:
Declaring a var at the controller class level works here instead of having a new instance inside a function:
Controller:
class HomeVC: UIViewController {
var event = EventManager()
override func viewDidLoad() {
super.viewDidLoad()
event.chooseCalendarTapped(presentingVC: self)
}
}
EventManager Class:
import UIKit
import EventKitUI
class EventManager: NSObject {
let eventStore = EKEventStore()
override init() {
super.init()
}
weak var delegate: EKCalendarChooserDelegate? = nil
var presentingVC: UIViewController? = nil
func chooseCalendarTapped(presentingVC: UIViewController) {
self.presentingVC = presentingVC
let authStatus = EKEventStore.authorizationStatus(for: .event)
switch authStatus {
case .authorized:
showCalendarChooser()
case .notDetermined:
requestAccess()
case .denied:
// Explain to the user that they did not give permission
break
case .restricted:
break
@unknown default:
preconditionFailure("Who knows what the future holds 🤔")
}
}
func requestAccess() {
eventStore.requestAccess(to: .event) { (granted, error) in
if granted {
// may not be called on the main thread..
DispatchQueue.main.async {
self.showCalendarChooser()
}
}
}
}
func showCalendarChooser() {
let vc = EKCalendarChooser(selectionStyle: .single, displayStyle: .allCalendars, entityType: .event, eventStore: eventStore)
// customization
vc.showsDoneButton = true
vc.showsCancelButton = true
// dont forget the delegate
vc.delegate = self
let nvc = UINavigationController(rootViewController: vc)
presentingVC?.present(nvc, animated: true, completion: nil)
}
}
extension EventManager: EKCalendarChooserDelegate {
func calendarChooserDidFinish(_ calendarChooser: EKCalendarChooser) {
print(calendarChooser.selectedCalendars)
presentingVC?.dismiss(animated: true, completion: nil)
}
func calendarChooserSelectionDidChange(_ calendarChooser: EKCalendarChooser) {
print("Changed selection")
}
func calendarChooserDidCancel(_ calendarChooser: EKCalendarChooser) {
print("Cancel tapped")
presentingVC?.dismiss(animated: true, completion: nil)
}
}
Upvotes: 1