skip to Main Content

I’m building an app that allows the user to add and create events in the Calendar native app for iPhone.
One of the features I’m working on is also to allow the user to add and create items in the Reminder’s native app of the iPhone.

From what I’ve read, the Calendar and Reminders app work with EventKit, and from the documentation, the process of each don’t differ too much.

I’m using this code to request permission to access Reminders and the code I use to add the items to the app.

Any thoughts on why is it not working?
Thanks in advance.

import Foundation
import EventKit

class EventModel {
    
    let eventStore  = EKEventStore()
    
    func requestAccessForReminders() {
        let status = EKEventStore.authorizationStatus(for: .reminder)
        if status == .authorized {
            print("EKEventStore access for Reminders already granted.")
        } else {
            eventStore.requestFullAccessToEvents { success, error in
                if success && error == nil {
                    print("EKEventStore access for Reminders has been granted.")
                } else {
                    print("EKEventStore access for Reminders request failed with error: (error?.localizedDescription ?? "Unknown error")")
                }
            }
        }
    }
    
    func addEventToReminders(title: String, startHour: Int, startMinute: Int, duration: Int) -> Void {
        
        let newEvent = EKReminder(eventStore: self.eventStore)
        
        newEvent.title = title
        newEvent.calendar = self.eventStore.defaultCalendarForNewReminders()
        
        do {
            try eventStore.save(newEvent,
                                commit: true)
        } catch let error {
            print("Reminder failed with error (error.localizedDescription)")
        }
    }
}

enter image description here

This is the information I have in the info.plist. (I know is the same message, but that shouldn’t be the main cause am I right?)

2

Answers


  1. If you use print to look at the behavior before save, you will probably find that:

    print ("defaultCalendarForNewReminders",eventStore.defaultCalendarForNewReminders() as Any)
    

    displays:
    defaultCalendarForNewReminders nil

    You should be checking defaultCalendarForNewReminders, because it can be empty, but .calendar cannot be.

    func defaultCalendarForNewReminders() -> EKCalendar?

    https://developer.apple.com/documentation/eventkit/ekeventstore/1507543-defaultcalendarfornewreminders

    var calendar: EKCalendar! { get set }

    https://developer.apple.com/documentation/eventkit/ekcalendaritem/1507169-calendar

    If you are working a clean simulator, the nil comes from checking from before the app was granted permissions. After permissions, you would see something like this:

    defaultCalendarForNewReminders Optional(EKCalendar <0x60000212af80> {title = Reminders; type = Local; allowsModify = YES; color = #007AFFFF;})

    Even if the Reminders.app was never run.

    Login or Signup to reply.
  2. Your primary issue is that you are requesting access to the calendar, not to reminders. Use requestFullAccessToReminders for iOS 17+ or requestAccess(to: .reminder) for iOS 16- instead of requestFullAccessToEvents.

    Here’s an updated version of your code that correctly requests access to reminders. This code handles iOS 17 as well as older versions of iOS.

    class EventModel {
        let eventStore = EKEventStore()
    
        func requestAccessForReminders() {
            let status = EKEventStore.authorizationStatus(for: .reminder)
            switch status {
                case .notDetermined:
                    func handleRequestCompletion(success: Bool, error: Error?) {
                        if let error {
                            print("Error trying to request access: (error)")
                        } else if success {
                            print("User granted access")
                        } else {
                            print("User denied access")
                        }
                    }
    
                    if #available(iOS 17.0, *) {
                        eventStore.requestFullAccessToReminders { success, error in
                            handleRequestCompletion(success: success, error: error)
                        }
                    } else {
                        eventStore.requestAccess(to: .reminder) { success, error in
                            handleRequestCompletion(success: success, error: error)
                        }
                    }
                case .restricted:
                    print("Restricted")
                case .denied:
                    print("Denied") // Offer option to go to the app settings screen
                case .fullAccess, .authorized: // fullAccess is for iOS 17+. authorized is for iOS 16-
                    print("Full access")
                case .writeOnly:
                    print("Write-only access")
                @unknown default:
                    print("Uh-oh, code is out-of-date")
            }
        }
    
        func addEventToReminders(title: String, startHour: Int, startMinute: Int, duration: Int) -> Void {
            let newEvent = EKReminder(eventStore: self.eventStore)
    
            newEvent.title = title
            newEvent.calendar = self.eventStore.defaultCalendarForNewReminders()
    
            do {
                try eventStore.save(newEvent, commit: true)
            } catch let error {
                print("Reminder failed with error (error)")
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search