Добавление события в календарь очень медленное

Я просто хочу добавить событие в календарь устройства.

Я использую:

 __weak ProgramViewController *weakSelf = self;

 EKEventStore *store = [[EKEventStore alloc] init];

    [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
     {
         if (error)
              NSLog(@"EKEventStore error = %@", error);

         if (granted)
         {
             NSLog(@"EKEvent *event ");

             EKEvent *event = [EKEvent eventWithEventStore:store];
             event.title = weakSelf.program.title;
             event.location = weakSelf.program.locationPublic;
             event.startDate = weakSelf.program.startTime;
             event.endDate = weakSelf.program.endTime;
             [event setCalendar:[store defaultCalendarForNewEvents]];
             NSError *err = nil;
             [store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

             if (err)
             {
                 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Calendar Error" message:err.localizedDescription delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                 [alertView show];
             }
             else
             {
                 UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Added" message:@"Calendar event added." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
                 [alertView show];
             }
         }
     }];

а в iOS 6 это может занять 6/7 секунд (iPhone 4), а в iOS 7 (на iPhone 5S) — ~10 секунд. Это нормальное поведение? Если нет, то что я делаю неправильно?


person daihovey    schedule 14.10.2013    source источник


Ответы (2)


Я была такая же проблема. Благодаря ответу Джаспера я задумался об очередях. Попробуй это:

    if (!err)
    {
        dispatch_async(dispatch_get_main_queue(),
        ^{
            [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"event added", nil) message:nil delegate:nil cancelButtonTitle:NSLocalizedString(@"ok", nil) otherButtonTitles:nil] show];
        });
    }

Вот зачем это нужно (см. выделение)

Обсуждение

В iOS 6 и более поздних версиях при асинхронном запросе доступа к хранилищу событий у пользователей запрашивается разрешение на использование их данных. Пользователю предлагается только в первый раз, когда ваше приложение запрашивает доступ к типу объекта; любые последующие экземпляры EKEventStore используют существующие разрешения. Когда пользователь нажимает, чтобы предоставить или запретить доступ, обработчик завершения будет вызываться в произвольной очереди. Ваше приложение не блокируется, пока пользователь решает предоставить или отказать в разрешении.

Поскольку UIAlertView — это UIKit, а UIKit всегда требует основной поток, любой другой произвольный поток приведет к сбою или непредсказуемому поведению.

https://developer.apple.com/library/ios/documentation/EventKit/Reference/EKEventStoreClassRef/Reference/Reference.html

person mmackh    schedule 19.10.2013
comment
Интересно, что это работает - вы все еще отправляете в основную очередь. - person Jasper Blues; 24.10.2013
comment
Хорошо сделано. @daidai, пожалуйста, измените, чтобы принять этот ответ - он будет более полезен для последующих зрителей. - person Jasper Blues; 24.10.2013

Согласно документам: "Объекту EKEventStore требуется относительно много времени для инициализации и выпуска". . . поэтому вы должны отправить это в фоновую очередь.

Кроме того, как ни странно, основная очередь занимает больше времени, чем фоновая очередь - не знаю, почему это так!

person Jasper Blues    schedule 17.10.2013
comment
Это очень странно - в моем тестировании это может занять до 30 секунд в основном потоке, в течение которых ваш пользовательский интерфейс заблокирован, тогда как поместите его в другой поток, и это произойдет практически мгновенно! - person siburb; 11.02.2014
comment
Мне нужно сохранить 40000 событий, и я уже использую фоновую очередь, есть ли какой-либо подход для достижения этой цели? - person Mrug; 04.01.2016