IOS/Objective-C: получить NSArray из блока завершения

Я пытаюсь получить массив EKReminders из блока завершения метода. Метод возвращает нужный мне массив. Однако я не могу найти хороший способ вернуть его в основной поток в известное время, чтобы я знал, что блок завершен.

Чтобы получить EKReminders, Apple требует подхода блока завершения (в отличие от EKEvents). Поэтому мой код выборки содержит следующее:

-(void) fetchReminders{
[self.eventStore fetchRemindersMatchingPredicate:predicate completion:^(NSArray *reminders) {
        self.reminders = reminders;
 }];
}

Приведенный выше код успешно запускается и после завершения помещает напоминания в ivar.

Проблема в том, что я не знаю, когда блок завершится, поэтому, если я просто попытаюсь получить доступ к self.reminders в viewwillappear после вызова вышеуказанного метода, он предположительно вернет пустой, потому что блок еще не завершен. Я хотел бы каким-то образом установить ivar когда я знаю, что блок завершился, чтобы устранить состояние гонки.

В ряде ответов на SO о том, как получить значение из блока завершения, рекомендуется передать блок завершения в метод следующим образом:

//change above method to 
-(void) fetchReminders withCompletion:(void (^)(NSArray *reminders))completion; {

and call it in viewwillappear with:
  [self fetchReminders withCompletion:^(NSArray* reminders) {
        self.reminders =remindersArray;
        NSLog(@"remindersArray in viewwillappear%@",remindersArray);
    }];

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

Буду признателен за любые предложения о том, как успешно получить в известный момент времени массив, полученный в блоке завершения.


person user6631314    schedule 21.02.2018    source источник
comment
Почему бы вам не вызвать метод, который вы хотите выполнить после настройки, например self.reminders =remindersArray; [self someMethodUsingReminders]; Если вы хотите, чтобы он был в основном потоке, тогда оберните вызов в dispatch_async и передайте основной поток   -  person Sandeep Bhandari    schedule 21.02.2018


Ответы (1)


Существуют различные способы достижения этого. Вы можете либо настроить наблюдателя значения ключа или NSNotification, либо выполнить необходимые действия в методе установки вашего объекта reminders, либо даже просто вызвать необходимые действия в этом блоке завершенияHandler.

Вызов из блока обработчика

-(void) fetchReminders{
   [self.eventStore fetchRemindersMatchingPredicate:predicate 
    completion:^(NSArray *reminders) {
        dispatch_async(dispatch_get_main_queue(), ^{
            self.reminders = reminders;
            [self doWhatYaGottaDoMethod];
        });
    }];
 }

Метод наблюдателя значения ключа
Когда ваше представление загружается, вы можете добавить наблюдатель значения ключа следующим образом:

[self addObserver:self
       forKeyPath:@"self.reminders"
          options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
          context:nil];

И реализуйте этот метод:

-(void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context{

     if([keyPath isEqualToString:@"self.reminders"]){
         //You got your reminders, do what you gotta do
      }
}

Обязательно удалите наблюдателей, когда ваш viewController отключен, иначе вы можете получить сбой.



person theCoderGuy    schedule 21.02.2018