В моем приложении мне нужно сделать https-вызовы для спокойного веб-API и обработать результаты по возвращении. Количество одновременных вызовов службы никогда не фиксируется, поэтому соответствующий код был написан соответствующим образом. Данные, полученные из службы, временно хранятся в базе данных SQLite в приложении. Ниже приведена структура, как это работает.
Когда пользователь переходит к любому экрану или его компоненту пользовательского интерфейса, для которого необходимо извлечь данные, контроллер представления вызывает метод для своего назначенного объекта модели. Затем этот метод проверяет, присутствуют ли данные уже в БД или их необходимо извлечь. Если данные присутствуют, они возвращаются контроллеру представления. В противном случае он инициирует асинхронный сервисный запрос и ждет, пока придет ответ, после чего возвращает данные в ВК. Таким образом, VC инициализирует индикатор загрузки перед вызовом указанной модели и закрывает его после возврата управления из этой функции.
Здесь важно, чтобы функция модели ждала ответа от веб-API. Это делается путем регистрации NSNotification, которое будет выдано служебным модулем после того, как возвращенные данные будут записаны в БД. Логическая переменная, для которой устанавливается значение false при выполнении запроса на обслуживание и значение true после получения ответа. NSRunLoop запускается при ложном условии этой логической переменной. Следовательно, когда для переменной установлено значение true, остальная часть обработки может продолжаться.
Ниже приведены соответствующие фрагменты кода, в которых все это реализовано:
[serviceModule initServiceCall:@"25" withDictionary:[NSDictionary dictionaryWithObjects:@[asOfDate] forKeys:@[@"toDate"]]];
dataReady=NO;
NSString *notificationName = @"dataReady";
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(useNotificationFromServiceModule:) name:notificationName object:nil];
NSRunLoop *theRL = [NSRunLoop currentRunLoop];
while (!dataReady && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);
Остальная часть функции продолжается после этого.
Это функция, которая обрабатывает уведомление:
-(void)useNotificationFromServiceModule:(NSNotification *)notification {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
dataReady=YES;
});}
Обычный процесс заключается в том, что после отправки уведомления NSRunLoop завершает работу, и остальная часть метода завершается, возвращаясь к контроллеру представления, который затем отклоняет индикатор загрузки. Проблема в том, что иногда этого не происходит. Пока выдается уведомление (вижу лог консоли), NSRunLoop не заканчивается. Индикатор загрузки продолжает появляться на экране и остается таким до тех пор, пока экран не будет нажат один раз. При касании экрана NSRunLoop завершается, а остальная часть процесса продолжается случайным образом.
Это происходит не всегда. Это происходит совершенно случайно, может быть, примерно 4-5 раз из 10. Пожалуйста, предоставьте некоторые входные данные/указатели, чтобы указать, почему это может происходить.
[theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]
. - person KudoCC   schedule 09.06.2014