Domanda

Can someone help me figure out what I'm doing wrong here. My app is supposed to access the iPhone's various calendars to check on upcoming events. So I need access to "events" in the calendar and also "reminders". When I have the events I store them temporarily in UserDefaults

In my .h file I have stuff like this

@property (nonatomic, strong) EKEventStore *eventStore;
@property (nonatomic, strong) NSMutableArray *calendars;
@property (nonatomic, strong) NSMutableArray *reminders;
@property (nonatomic) BOOL accessToCalendarsGranted;
@property (nonatomic) BOOL accessToRemindersGranted;

and I need to get permission from the user to access these so in the main code I have code like this:

    -(void)requestCalendarAccess
{
    // Prompt the user for access to their Calendar

    [_eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error){
        if (!granted)
        {
            NSLog(@"user has not granted access to calendars!!");
            // Display a message if the user has denied or restricted access to Calendar
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Privacy Warning", nil)
                                                            message:NSLocalizedString(@"Permission was not granted for Calendar", nil)
                                                           delegate:nil
                                                  cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
                                                  otherButtonTitles:nil];
            [alert show];

            return;
        }

        // Let's ensure that our code will be executed from the main queue
        dispatch_async(dispatch_get_main_queue(), ^{
            // The user has granted access to their Calendar
            [self accessGrantedForCalendar];
        });
    }];
}

which is finished off by the code in accessGrantedForCalendar

_calendars = [[NSUserDefaults standardUserDefaults] objectForKey:kCalendarListKey];

//if we have calendars stored in user defaults, we go and read them
if(!_calendars)
{
    _calendars = [[NSMutableArray alloc] init];
    NSArray *phoneCalendarArray = [_eventStore calendarsForEntityType:EKEntityTypeEvent];

for (EKCalendar *systemCalendar in phoneCalendarArray)
{
    NSMutableDictionary *calendarDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[systemCalendar title], kCalendarName, [systemCalendar calendarIdentifier], kCalendarIndentifier, [NSNumber numberWithBool:YES], kCalendarWatched,  nil];

    [_calendars addObject:calendarDict];
}

[[NSUserDefaults standardUserDefaults] setObject:_calendars forKey:kCalendarListKey];
[[NSUserDefaults standardUserDefaults] synchronize];

}

And this all works fairly well now. Lots of other code for actually getting events not included here. The problem comes when I try the same approach for reminders:

-(void)requestRemindersAccess
{
    [self.eventStore requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError *error){
        if (granted)
        {
            // Let's ensure that our code will be executed from the main queue
            dispatch_async(dispatch_get_main_queue(), ^{
            // The user has granted access to their Calendar
                [self accessGrantedForReminder];
            });
        }
        else
        {
            NSLog(@"user has not granted access to reminders!!");
            // Display a message if the user has denied or restricted access to Calendar
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Privacy Warning", nil)
                                                            message:NSLocalizedString(@"Permission was not granted for Reminders", nil)
                                                           delegate:nil
                                                  cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
                                                  otherButtonTitles:nil];
            [alert show];
        }
    }];
}

and the code which finishes this in accessGrantedForReminder:

_reminders = [[NSUserDefaults standardUserDefaults] objectForKey:kRemindersListKey];

//if we don't have reminders stored in user defaults, we go and read them
if(!_reminders || _reminders.count == 0)
{
    _reminders = [[NSMutableArray alloc] init];
    //FOLLOWING LINE HAS PROBLEM FIRST TIME!!!
    NSArray *phoneReminderArray = [_eventStore calendarsForEntityType:EKEntityTypeReminder];

for (EKCalendar *systemCalendar in phoneReminderArray)
{
    NSMutableDictionary *calendarDict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[systemCalendar title], kCalendarName, [systemCalendar calendarIdentifier], kCalendarIndentifier, [NSNumber numberWithBool:YES], kCalendarWatched,  nil];

    [_reminders addObject:calendarDict];
}

[[NSUserDefaults standardUserDefaults] setObject:_reminders forKey:kRemindersListKey];
[[NSUserDefaults standardUserDefaults] synchronize];

}

The line indicated above has a problem - the first time I run the application (i.e. immediately after receiving permission) I see phoneReminderArray has zero objects in it. If I exit the program and run again phoneReminderArray will get one object. It's driving me nuts - why does it only work after I exit the app (while the other calendars Home, Work & Birthdays) all seem to come up right away?

Any ideas anyone?

FYI I looked at this related question and it helped me figure out my initial problems with the first lot of calendar events, but it's not helping for Reminders

È stato utile?

Soluzione

The solution is actually very simple. Right before your call to the following line for fetching reminders:

  NSArray *phoneReminderArray = [_eventStore calendarsForEntityType:EKEntityTypeReminder];

Place this line:

[_eventStore reset];

this should fix your problem.

Altri suggerimenti

I wasn't able to get it to work after talashar's answer, I also tried the similar refreshSourcesIfNecessary method to no avail.

What did work for me: I had to call this line before asking for the list of reminder calendars:

[_eventStore defaultCalendarForNewReminders];

After that, I was able to get the list of reminder calendars with:

[_eventStore calendarsForEntityType:EKEntityTypeReminder]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top