App Services • iOS, OS X • 50:04
Event Kit provides access to users' Calendar Events and now allows access to Reminders as well, on both iOS and OS X. Be sure to pencil this session in to hear from the experts on how to fetch and write Calendar Events and Reminders, and how to make the best use of the Event Kit framework.
Speakers: Scott Adler, Jeffrey Harris, Matt Lanter, Aaron Thompson
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Then Event Kit Data Isolation, which is a feature currently on iOS that you're going to need to pay attention to if you're writing new apps or even just to retrofit your old apps. Finally, we'll be talking about Calendar Store on OS X. Calendar Store is the API that you would use in versions of OS X before Mountain Lion if you wanted to work with Events and Reminders. Alright, let's get started with Calendar Events.
So, Calendar Events are here. If you're working with Event Kit and Calendar Events, you're working with the same persistence as is used on the iPad and the iPhone and OS X for Events and Reminder. But in this case, we're talking about Events. So, one of the new features in Mountain Lion is that if you do not have Calendar running and you create new Events, they will still sync to Exchange and CalDAV accounts.
Those of you who have been working on OS X before, that should be good news. Alright, so let's actually talk in more detail about why you would care about Calendar Events. So, you're out there making your awesome apps, thank you very much, and you're moseying along and things are going well, and then one day you meet someone and you fall in love.
And you decide, "Hey, let's get married!" And you do, but it turns out there's all this planning involved in getting married. If you've done it before, you'll know this is true. You'll know that you're getting married. But if you've done it before, you'll know this is true. But if you've done it before, you'll know this is true.
And you have to get together with the venue to plan out exactly how things are, and scheduling with them is a hassle, and get together with the cake maker and plan things out. And so, you and your super geeky spouse, you get married, but then you think, "That was a hassle.
Let's make it easier for somebody else next time. Let's make awesome wedding!" So, awesome wedding, you decide, is going to be this app that is going to help other people plan out all of the details. Remember the details about the florist, remember the details about making cake and things like that.
So, if you put it on the app store just with those details, I think it would do well, but what's going to happen is your users are going to plan out the cake testing, and they're not going to see it on their calendar. Because you haven't put it onto their calendar, and they will plan to go golfing instead, or something like that. And that's not going to work out so well with your spouse.
So, what you really want in this case is you want your users to see the events that are important to them that you're working with and put them on their calendar. So, just having events that are important to them is going to help you plan out all of the details.
So, having events on your users' calendars is great, and that draws them in with the things that you're doing in your apps. Some other benefits are that you can put a link back to your application and draw users in that way. And you can also add alarms so that users don't forget to go and do the cake testing.
Okay, so let's talk about the elements of EventKit and how you go about not missing your cake testing. So, here is the OS X calendar app, and in the left-hand corner, left-hand side, you see here are a bunch of calendars. The calendar app contains many calendars, and then each calendar contains many events.
[Transcript missing]
So, EK Event, we talked in great detail about at that session a few years ago, so I'm not going to go into great detail, but we'll just show here the iOS Event Editor and the OS X Inspector. Most of the fields you see here, you can edit in your EK Events.
All right, so let's look at some actual code. Here is the events in a week shown in OS X Calendar. Let's walk through the code that you would use if you wanted to have an application, an app, that would fetch all of the events in your Calendar for a given week.
So the first thing we need to do, as we were just discussing, is create an EK Event Store. And in this case we're going to initialize it with EKEntityMaskEvent, because we're interested in events. Next, we want to find all of our calendars, but actually we don't want all of our calendars, we just want the calendars that involve events. So we're going to fetch calendars for entity type EKEntityTypeEvent.
Then once we have event calendars, we want to create a predicate that will describe the fetch we want to run. So the predicate needs to know what the start of the range is, the end of the range, and which calendars you're working with. So I'm not going to go into detail right now about how you create an NSState for the beginning of the week or the end of the week, we'll actually talk about that later, but let's imagine that you have some NSStates for that and we create a predicate.
And then with that predicate, it's as easy as saying Store Events Matching Predicate. And then you have an array and you can iterate over it and we can print them out with their titles and start dates. And you have a not very well sorted utility for printing out the events in your week.
All right, well, with that, now that we've talked about EK Calendar and EK Event Store, I'd like to invite up my colleague, Matt Lanter, to give you a more in-depth demo using Calendar Events. Thank you, Jeffrey. I'm Matt Lanter, and I'm an engineer on the Calendar team. Outside of work, I like playing poker with friends.
A few months ago, a group of my friends and I had an impromptu game of poker. It was a ton of fun. Some of us won money, some of us lost money, but we all had fun, which is all that matters. So much fun, in fact, we invited more and more of our friends to join. Unfortunately, it's become harder and harder to find the time that works for all of us. We tried solving this using iMessage, which works okay, but it's hard to keep track of the times everyone is suggesting.
Given that I always have my phone with me, and I'm often at my computer, this seems like a great opportunity for an app to solve this problem. Let's look at an app I created that does just this. First, I created a shared calendar called Shared Poker and invited all my friends to it. Then they can just open up this application, select that calendar, and they can suggest a time that works for them to play poker.
[Transcript missing]
I used Event Kit to create this application. The great part about using Event Kit is that I was able to use the exact same model code on both iOS and OS X. Here's the iOS version, and here's the OS X version. They have different views and controllers, but it's the exact same model code underneath them. Let's look at a couple of the methods we need to implement in the model.
First, we need to fetch the Calendars. We'll use this to populate the drop-down list so you can select the shared Poker Calendar. Second, we need to be able to view all the upcoming Events so we can display that in the Table View. Third, we want the ability to create Events so that my friends can suggest times that work for them. And finally, the most important part of this app is voting, so that we can find the time that works best for all of us.
Let's go into Xcode and look at how we'd implement these methods. First we'll start out and look at what the application, the app looks like with none of these implemented. So just the view. And then we'll go through and implement them one at a time and see what it looks like after we do that. If we go to the demo machine, we see here's the application in the middle. Currently it doesn't display anything though. If I click Calendars, nothing happens. There's nothing in the list and adding an event does not work either.
So let's go into Xcode and first we'll do the init method and then we'll get into some of those methods. Here we have an init. As Jeffrey mentioned earlier, we want the event store to be long-lived ideally. So we'll store that as an instance variable, as a property within our model.
To do this, we'll call init with access to the types and we'll specify events. The entity mask event. We only care about events in this application, this app. We don't care about Reminders. Next, we also want to keep track of the Calendar the user currently has selected in the UI, which we'll use in some of our later methods.
We need a good default starting value though, so we'll use the default Calendar for new events. This is the Calendar the user specified in the Settings app on iOS or within Calendar Preferences on OS X. In addition, we have some data structures we use in this model to basically store the current events we're showing to the user. We're not too concerned about those for the demo, but we'll initialize them here.
Finally, when we fetch the Poker Events, we want to do this on a background thread so we don't block the UI while that's happening. We'll use Grand Central Dispatch, which is a great API available on both iOS and Mac OS X, to do this. We need to create a queue as part of this. So we'll create the queue, and we'll call dispatchQueueCreate, give it a title, and then specify some options. In this case, it's a serial queue, meaning only one thing runs on it at a time.
Okay, so that's our NIT method. Let's look at how we fetch the Calendars. Here we have a method, Calendars. Currently it just returns empty array using the new Objective-C array literal syntax. Let's think about what we want to do here. We want all of the events supporting Calendars. We don't care about the ones that only support Reminders.
And then we want the ones that are writable, that we can add events to. So to get the ones that support events, we will call Calendars for Entity Type on the Event Store and we'll specify Entity Type Event. We need to filter this down though to the writable ones. So we'll create an array to store the filtered results.
Just in the rain, we'll call that Filtered Calendars. Then we'll iterate through the All Event Calendars. And so for each Calendar and All Event Calendars, we want to check if we can add Events to it. So we'll check, does the Calendar allow content modifications? Basically, can we add items to it? If so, we'll add that to Filtered Calendars, and then we just want to return that Filtered Calendars array.
I will run this by clicking "Run" in the upper left-hand corner, and we should hopefully see that we now have the shared poker calendar, as well as my home and work personal calendars. Currently, though, I can't view the times my friends have suggested. So let's look at how we'd fetch all the upcoming events so we can populate the table view.
Here's a method, FetchPokerEvents, which we'll use to do that. As I mentioned earlier, we want to do this on a background thread so we don't block the UI. We'll use Grand Central Dispatch. and we'll call dispatch async and we'll specify that queue we created earlier. Now, we want to fetch the events within a current range. For this demo, I arbitrarily chose one day in the past to two months in the future. We need to create NSDates that represent these points in time so we can then fetch within that range. To do this, we need the user's current NS Calendar.
So we'll call Current Calendar, and then we'll create NSDate components. So one day ago components, we'll set the day to -1, but we need an NSDate. To get the NSDate from the NSDate components, we'll call dateByAddingComponents to date. So we'll specify the components we just created, the NSDateDate, this returns the current date time, and that will return the NSDate one day ago.
We want to do the same thing for two months in the future. So here we do that. The main difference is our month is a positive 2. Now that we have those two NSDates, we want to get a predicate from the Event Store that encapsulates those two dates and a calendar we'll search in.
will call the predicate for events with start date, specified one day ago. The end date is two months in the future, and the calendars we will use the new Objective-C array literal syntax. So this takes in an NSArray. So we're basically specifying an NSArray with the selected calendar we created in a Nib. Now that we have this predicate, we want to run it to get the matching events.
We will, on the Event Store, call Events Matching Predicate, pass in that predicate, and that will give us an array of results. We need to filter this down, though, by title. We only want the events whose title is Poker. We'll create a standard Dennis predicate to do this.
So we'll call a predicate format where the title, so I counter that title, matches our parameter, which in this case is poker. Then we'll just run that predicate by calling filtered array using predicate, passing that predicate, and we'll set that back to our results array. Now that we have this array of results, we want to update those data structures we created in there. We're not concerned about everything we do as part of that for this demo, so we have a helper function that will do that. update those internal data structures.
Now that we have gotten all the results, we want to notify the UI so that it can update and refresh and show the user the latest events. We want to do this on the main thread since it's likely the UI will do some work when it gets a notification.
We will dispatch async back onto the main queue, which runs on the main thread, and we'll post a notification saying our model changed. I'll run this again, and now we should hopefully see all the upcoming events. So we see here, Shared Poker, and then we see all the upcoming events.
So we see today at 6:00 p.m., tomorrow 7:00 p.m., and then Friday at 8:00 p.m. Currently, tomorrow is winning. However, I would really like to play tonight at 10:00 p.m., so I'd like to create a new time. Unfortunately, I can't do that yet. Because we can't add new Events, so let's look at how we would add Events.
Here we have Add Event with Start Time, which takes in the start time. And first we want to create a blank EK event. Then we'll set a bunch of properties on this event, and finally we want to save this event. To create the blank EK event, we'll call EK event, Event with Event Store, and this will basically create a new event that's bound to the specified Event Store.
Now we want to set several properties on it. So here we set the title, time zone, start date, end date, and for the demo we just always assume the duration is one hour. And then we specify what calendar this event should go into. We want to save this event now.
So we'll call saveEvent, pass in that event. We specify a span. The span only matters for non-recurring events. Or sorry, it only matters for recurring events, and this is not a recurring event. So it doesn't really matter what we put here. But if you'd like to learn more about recurring events, I'd suggest watching the WWDC talk from two years ago. We specify that we commit yes, so we'll immediately commit this. And then if there's an error for some reason, we'll log that out. The example of an error would be if I did not specify the start date, I would get an error.
Let's run this and we should hopefully see, we see all the times people suggested. I'll create one for 10:00 PM tonight. And now we see 10:00 PM. Awesome. I'd like to vote on this though, so I can convince my friends to come to this time tonight. We have increased vote on event, which takes an event.
First, we want to get the current phone count. So we'll call Event Number of Votes. You may be thinking, "I've never realized there's a Number of Votes field on an event." This field is created using custom code, specifically using a category, which I did for this demo. We stored it in the Notes field for this demo for simplicity's sake. In an actual application, you might want to store it on an external server and then tie it back to this event with some sort of event identifier.
But now that we have this number of votes, we want to increase it by one. So we'll just set the number of votes plus one. And since we modified the notes field, we want to save this event. We'll call Save Event, and this is the same thing we just did when we created a new event.
We'll run this again, and hopefully I should be able to vote on it. So here's the one I just created. I'll click. And now we have one vote, which is awesome. We will -- the great part about this, as I mentioned earlier, is I can use the exact same model code for both iOS and OS X.
So let's try and-- let's build the iOS version. And I already created the Viewer and Controller for it. I just need to run it, and then hopefully it will use this model we have just created. So I'll switch to the mobile target. Build this. And then we'll switch to my device. And here we see the application running. We see the 10 PM one I just created. I'll click on that and increase the vote to 2.
We see in this application, we see all the times my friends have suggested. I can click Calendars in the upper left-hand corner if I want to change the calendar. I can create a new event using plus in the upper right-hand corner. And so that's iOS application. And this uses the exact same model code we just created. If we go back to the demo machine.
We see that it is automatically updated, so the 10:00 PM one has two votes now. This is great. Event Kit takes care of all the syncing for you behind the scenes. You notice all we do is we save the event and then everything is taken care of for you.
Okay. I'm showing you... and I will be talking about how easy it is to create an application using Event Kit. The great part about Event Kit is you can have the exact same model code to create both an iOS and an OS X version of the app. Now, over to Aaron, who will talk to you more about Reminder.
I'm Aaron, I'm an iOS Event Kit Engineer, and I'm excited to talk to you about Reminder in Event Kit today. In iOS 5, we introduced this great new Reminder app that helps you keep track of all the things you have to do on both your iPhone and iPad.
And then in the OS X Mountain Lion, we brought it to the Mac, so your Reminders are really useful because they're on all your Apple devices. But there's one place they haven't yet been, and that's your apps. So now I'm excited to show you how you can integrate Reminder into your own apps. And I'm looking forward to seeing the interesting and awesome ways you use them in your apps.
So, you may already be familiar with something that uses Event Kit Reminders. That's Siri. Siri has been using Event Kit behind the scenes to create Reminders when you ask it to. So, to go through this, let's take an example of a task I've been putting off for a while.
My cat has started smelling a little bad lately and I need to give her a bath. And some of you know all too well why I might have been putting off this task. So I'm going to ask Siri to create a Reminder to help me. I want to ask Siri, "Remind me to give my cat a bath." Up will pop something like this.
A reminder. So, how would we create this using Event Kit code? Well, we're going to start out just like we were doing to create an EK event. That is, we need an EK Event Store. And because we want this to be an Event Store for Reminders, we'll in it with access to Entity Types and pass in EKEntityMaskReminder.
Next, we need an EK Reminder object to represent this Reminder. So we'll just create this using Reminder with Event Store. Next, we're going to set a couple of properties on it. First, the title, "Give My Cat a Bath," and then the Calendar. Now, when you create an event or a Reminder through Siri, it'll use the default list for new Reminders that you specified in your settings. So we're going to do the same here by using default Calendar for new Reminders. Next, all we have to do is save that Reminder using EK Events Store's SaveReminder method.
Now, I might keep putting off this event, or this task, if it never pops up and reminds me. So let's talk about how to create a time-based Reminder. If I were asking Siri, I'd ask, "Siri, remind me to give my cat a bath tomorrow at 4:00 p.m." Let's look at the code.
To represent when I want the alarm to fire, I'll use an EK alarm, alarm with absolute date specifically. If you're already familiar with creating alarms on events, it works very much the same way. Now, you'll notice here that we kind of left out how to get this tomorrow at 4:00 p.m. date, but this bears more investigation.
[Transcript missing]
This is... How many of you know what this number means? 86,400. That's the number of seconds in a day, right? Except when it's not. Thanks to our good old friend Daylight Savings Time, this will be wrong probably twice per year, but only probably in inconsistent locales and at inconsistent times on inconsistent days.
So, how on earth are we going to get this right all the time? We're going to use NS Calendar, like Matt mentioned earlier. Specifically, we want to use the Gregorian Calendar because Event Kit for Reminders at this time only supports the Gregorian Calendar. So, now that we've specified this NS Calendar, we need to go from today to tomorrow. So, we'll use NSDate Components and set its Day Component to 1.
Next, we want to add one day to the current date. If you're not familiar with the NSDate API, NSDate is simply a wrapper around an absolute time, and the date method returns an absolute time for the current time right now. So, I'll use that calendar to get a new NSDate for tomorrow by adding these one-day components to the current date.
Now that I have the NSDate for tomorrow, what I need to do is get the components out of that so that I can set them to a specific time. So I don't care about the hours, minutes, and seconds yet. I just want to get the year and the month and the day for tomorrow. We're going to put in an era just for future forward compatibility.
Then, so you see we have the components from that date, and that'll give us, and as a date components for tomorrow at 4:00 PM, sends the time. Then we want to specifically set the hour to 16, this is 24 hour time we're dealing with, and then we'll set the minute and second to zero.
And finally, one last thing, because the EK Alarm API wants an NSDate, not NSDate components, we're going to get an NSDate back from those components using NSCalendar's dateFromComponents method. All right, so we're done talking about how to get this crazy date, but it'll be right in all locales and all time zones.
Again, we're going to create this EK alarm with an absolute date, and then we're going to add that alarm to the Reminder. Before we save though, there's one last step. We have to set the due date components as well. This helps it show up as overdue after the Reminder has fired in the Reminder's app. So, we're going to set the due date components property to those NSDate components that NSCalendar helped us calculate just a second ago. Finally, we'll save that Reminder. Now, let's talk about location-based Reminders.
We all know that giving a cat a bath can be very hazardous to your health. So, I'm going to want a little bit of armor. Specifically, I want to ask Siri, "Remind me to pick up a chainmail suit when I leave work, so those claws of fury don't leave a flesh wound." So, how do we create a Reminder that looks like that? We're going to use an EK structure location object. This is new in the new Reminder's API. This will create using location with title. And the title here is something that you use to show your users what this location is.
Next, we need to show where on earth work is. So we're going to use the CLLocation class for that. Now, normally you might want to use CL Geocoder or some other core location APIs to get this for you. But I just happen to know the location for work off the top of my head. So I'm going to create this CLLocation object using a latitude and longitude specifically. Then I need to set that on the structure location as the geolocation property.
Next, this is still an alarm after all. It's still popping up at you. So I'm going to create an EK alarm just using alloc init without any date or time. and next I'm going to set a couple properties on it. First, the structure location to what we just created, and then because I want this to be when I leave work as opposed to when I arrive at work, I'm going to set the proximity property to EK_ALARM_PROXIMITY_LEAVE. Finally, as before, I'm going to add this alarm to the Reminder and save the Reminder.
All right. Now, what if my poor cat gets dirty on a regular basis? How do I have it remind me to give my cat a bath every month, for example? If I were asking Siri this, she'd pop up something like that. In code, it's easy. We'll use an EK recurrence rule to represent how it repeats. If you're already familiar with Event Kit for Events, this should be old hat to you. So, we'll create this recurrence rule with a recurrence frequency of monthly and an interval of one to specify that it's every month.
Then, we're going to add this recurrence rule to the Reminder. And before we save, there's one more step. We have to set the start date components for when it starts repeating. Now, we already talked in depth about how to get the NSDate components for any time, so I'll just use the NSDate components for right now. Finally, we're going to add a new rule to the Reminder. to save this reminder.
Now, there is a slight difference in how Events and Reminders that repeat regenerate. If you look in your Calendar, you'll see repeating Events generating out indefinitely. However, if you look in the Reminders app, you don't see a million Reminders of the same thing. You only see the next one that's not due, that hasn't been completed. So, once you check that one completes in the Reminders app, that's when it will generate the next instance. Speaking of checking reminders complete, let's talk about how to do that.
In the Reminders app, if I were to check a complete, it would go from looking like that to that. And that's what we call the completed card. So, how do we do that in code? Simple. All we have to do is set the completed property and then save the reminder.
Now, the completion date, which you'll see right there, is when you completed an event or a reminder. It's automatically set to the current time when you set this completed property to "yes" and save the reminder. But what if you were importing some old data and some of the reminders in that old data were already completed at a specific time that you know? Well, to set that arbitrary time in the past, we would use the completion date property of EKReminder.
All right, so that's all there is to it. We've gone over how to create all sorts of Reminders, including time-based Reminders that fire at a specific time in the future. We talked about how to use location-based Reminders using EK Structured Location. And we talked about how to make Reminders that repeat using EK Recurrence Rule. And finally, we all know how to mark a Reminder done. So that's great, but what if I have an existing app that uses Reminder? I'd like to invite up Scott to talk about that.
[Transcript missing]
Next, we're going to set the title to the name of the ingredient and the notes we'll set to the amount. And then finally, we're going to save each Reminder. Now, the important thing here, and we haven't really talked about this too much, is that in this Save Reminder call, we're going to set Commit right here to No.
And the reason we're doing that is if you were to set Commit to Yes, we'd have a database save every single Reminder that you're creating. So if you had 50 ingredients, there'd be 50 database saves. That'd be kind of slow. So we're just going to say Commit No. And then at the very end here, we're going to commit the whole thing. And then we're going to call Event Store.
So what that'll do is that'll then actually do a database save of all those Reminders that you didn't commit before. So it's just a little optimization. And then I just added a little UI alert view in this case that will put up an alert saying, hey, your Reminder was created. So let me show you an example of what that looks like here.
And so here's my Recipes app. and these are all my recipes, and if I pick Chocolate Cake, I can scroll down and here's my new Create Shopping Reminders, and it's right after my whole list of ingredients, so I'm gonna tap this. And it gets my alert up that says Shopping Reminders have been added. So if I say OK here, If I go to the Reminder app, here's my regular Reminder list and there's now Chocolate Cake, which was just created. And there's my Chocolate Cake. So that's the basic demo.
So next I wanted to talk about something that's new in iOS 6, which is Event Kit Data Isolation. So exactly what is it? Well, this is what's under Privacy and Settings in iOS 6. We've talked a lot about this in other sessions. But the point here is that your apps now have to ask for permission to get to Reminders and Events. So when you want access to it, we're going to ask the users, just like you were used to with location in the past.
So they're prompted whenever your EK Event Store is instantiated. Now this is really important to remember because we want you to keep your EK Event Store around a lot, but we don't want you to create it right at the beginning of your app unless it's needed right at the beginning of your app.
So the reason for this is that, like in the Recipes application, we don't want to ask to access Reminder when they're just looking at their recipes. We only want to ask them when they actually tap on the Make Shopping List. And that's because they don't want necessarily to say, "Yeah, I want to look at my recipe. Why do you need Reminder?" They want it to be at the time they're doing something that actually needs access to Reminder.
Now if you're writing something that's reading Reminder right away and doing stuff, then create your EK Event Store right away and you'll ask the user. Now this will only ask the first time they ask for it and then they'll decide yes or no, and then the next time your app runs and you won't ask again.
Now the important thing is when we do ask that your code is not blocked. This is an asynchronous call that brings up this alert view. Now it's important because you may have written apps in the past that just go ahead and do stuff if you're doing events. If you're doing reminders, it's all new.
So you should do this correctly. But if your app exists right now and you just go and do things, you may get errors like if you try to save things before the user has said yes, you have access, you might actually get errors back saying you don't have access to do this. So we'll show you some tricks on how to deal with this.
Then what happens is, while your app is, while the asynchronous dialogue is up, your app will eventually get an Event Store Change Notification, and then you'll be able to check and see what did they say. Did they say, "Yes, you're allowed," or, "No, you're not allowed." And then what's really important is this usage description. Now that's what's highlighted in yellow here, and that's what you're going to be automatically shown to the user saying why you need access to Events or Reminder.
And it's really important to be specific here and cover any of the cases that your app might use. You're only going to be asked once for your whole app, so if you have multiple places you're using Reminder or multiple places using Events, make sure it covers those cases. But try to give something clear that people, that everyday people, not just developers, will understand.
So let me show you how we do this. And if we go back to, I have some code way up here. So I'll comment out this Make Shopping List. and I'll show you the code we wrote to actually make the shopping list, this time dealing with data isolation.
You might recognize the beginning of this. We create the Event Store. Same thing as what we did before. And again, we're creating it when they hit the button. That's the important thing is that we'll be asked when we hit the button. and then we actually are going to register for the Event Store Change Notification, which will call this function Event Store Changed.
Then we're going to check our authorization status. Now, the main thing here with checking authorization status is that we want to see if they've already been authorized, they've already been denied or restricted, and also if they're pending. And pending is that asynchronous call I talked about. So if we're authorized, we're just going to go ahead and create the Reminders just like we did before.
If they're denied or restricted, we're going to put up an alert that we have created, that you will create, or however you want to deal with them being denied or restricted. And in this case, we put up an alert that says you're not allowed to use this and to use Reminders, and you can go change it in your settings if you want to.
If they're restricted, that could be someone turned on restrictions that doesn't allow us to even ask them because you're not allowed to change your access to Reminders. And then if they're not determined, that's the asynchronous call. So in this case, I added a flag to this view controller saying we're pending authorization, and I'm going to set that flag, and then I'm not going to do anything until we get our notification back. So let me show you that notification.
We don't change the code at all for Create Reminder, same code as before. and here's our event store changed function. And what we're going to do is if we were setting this pending authorization flag, then we're going to go in and we're going to look and see what our current authorization status is. Most likely they've changed the authorization status.
So if it's now determined, we're going to go and we're going to say, okay, are we authorized? If we're authorized, we create Reminder. If we're not authorized, we're going to present an alert that says, hey, you're denied, you're not allowed access to Reminder. Now there's one other thing I didn't show, which is here inside the info P list, let's see if we can -- it's kind of small here, but if you can see down here, there's this Reminder's usage description. And there's also other ones for contacts usage description and calendars and location.
So what you do is you set in here that user presented string that says why you need access to your Reminders. And you can -- we just said create new shopping list for recipe ingredients here. So that's where you're going to set it for your whole application. So you might have different -- you might use locations, you might have one for location in there.
And then we can just build and run this. So let me go to my phone here. So I actually am running the version that knows about restrictions or knows about privacy. So let me go to settings and show you how this shows up in settings. So we go inside of privacy.
and we can go to Reminder and you'll see that Recipes has already been given access. So what I'm going to do is I'm going to turn off Recipes and no longer allow access and you'll see how this works. So I'm going to go back to Recipes.
[Transcript missing]
I scroll down here, I'll say Create Shopping List. And now this is a system alert that comes up with our usage string right here in here. So it says create new shopping list for recipe ingredients, and I can allow or not allow. So if I say allow, what's happening behind the scenes is we're talking to the system service that is going to allow us to create Reminders, and then we get our message back. So we can see that it actually worked. And if I go to the Reminders app, we'll see that I actually have now grapes right there. And that's it. And that's everything.
[Transcript missing]