Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Futhark

macrumors 65816
Original poster
Jun 12, 2011
1,238
179
Northern Ireland
I've written an app that allows a user to write some text in a text field and select a date and time on a date picker and when they press a button it sends the text and saves it in the Reminders app at the selected date and time, The problem I'm having is the first appointment never gets saved for some reason? I get the message saying that my app would like to access Reminders which I allow, I then get the popup I created saying appointment created successfully but when I check the reminders app there is nothing there. Once I fully close down the app and reopen it and do the process again it works perfectly every time, Just not the very first one when I'm to click the allow button. here is my code if anyone can figure out what I have done wrong it would be much appreciated:

Code:
import UIKit
import EventKit

class FirstViewController: UIViewController {
    
    @IBOutlet weak var reminderText: UITextField!
    @IBOutlet weak var myDatePicker: UIDatePicker!
    let appDelegate = UIApplication.shared.delegate
        as! AppDelegate
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
    }
    
    @IBAction func setReminder(_ sender: AnyObject) {
        
        if reminderText.text == "" {
            
            // Create the alert controller
            let alertController = UIAlertController(title: "Information Needed", message: "Please type in your treatment and select the correct date and time you wish to be reminded about before pressing the Create Appointment Reminder button.", preferredStyle: .alert)
            
            // Create the actions
            let okAction = UIAlertAction(title: "Got It", style: UIAlertActionStyle.default) {
                UIAlertAction in
                NSLog("OK Pressed")
            }
            
            // Add the actions
            alertController.addAction(okAction)
            
            // Present the controller
            self.present(alertController, animated: true, completion: nil)
            
        } else {
            
            if appDelegate.eventStore == nil {
                appDelegate.eventStore = EKEventStore()
                appDelegate.eventStore?.requestAccess(
                    to: EKEntityType.reminder, completion: {(granted, error) in
                        if !granted {
                            print("Access to store not granted")
                            print(error!.localizedDescription)
                        } else {
                            print("Access granted")
                        }
                })
            }
            
            if (appDelegate.eventStore != nil) {
                self.createReminder()
            }
        }
        
        self.reminderText.resignFirstResponder()
        
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        
        textField.resignFirstResponder()
        
        return true
        
    }
    
    func createReminder() {
        
        let reminder = EKReminder(eventStore: appDelegate.eventStore!)
        
        reminder.title = reminderText.text! + " " + "(Pose Beauty Salon)"
        reminder.calendar =
            appDelegate.eventStore!.defaultCalendarForNewReminders()
        let date = myDatePicker.date
        let alarm = EKAlarm(absoluteDate: date)
        
        reminder.addAlarm(alarm)
        
        do {
            try appDelegate.eventStore?.save(reminder,
                                             commit: true)
        } catch let error  {
            print("Reminder failed with error \(error.localizedDescription)")
        }
        
        // Create the alert controller
        let alertController = UIAlertController(title: "Reminder Created Successfully", message: "Your \(reminderText.text!) appointment reminder at Pose Beauty Salon has been successfully created in your iPhone Reminders app.  Thank You! ", preferredStyle: .alert)
        
        // Create the actions
        let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) {
            UIAlertAction in
            NSLog("OK Pressed")
        }
        
        // Add the actions
        alertController.addAction(okAction)
        
        // Present the controller
        self.present(alertController, animated: true, completion: nil)
        
        reminderText.text = ""
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        reminderText.endEditing(true)
    }
}
 
Your completeReminder() function is being ran before you actually have access to add reminders the first time which blocks you out from modifying the store - requestAcesss is asynchronous.

It works in the second app launch because you have given it access in the prior session and the app was restarted (equivalent to calling reset on the store). Here is a relevant piece of info from the docs:

If your app has never requested access before, you must request access to events or reminders before attempting to fetch or create them. If you request data before prompting the user for access with this method, you'll need to reset the event store with the reset() method in order to start receiving data after the user grants access.

I believe you should be getting an error in Console complaining about permissions and a failure to write.
It would be beneficial for you to include the success alert in your do block after you try to save your reminder. Then if a failure occurs, the execution in that block stops and you won't receive the false-positive message saying it worked.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.