Как использовать события пользовательского интерфейса при загрузке данных в фоновом режиме
У меня есть небольшое приложение для iPhone, которое загружает данные из веб-службы. Чтобы убедиться, что при загрузке данных ничего не происходит неправильно, я создаю полупрозрачное представление поверх приложения и использую CFRunloopRun(), чтобы дождаться загрузки всех данных в фоновом режиме. Вот код для этого:
self.connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
// Now show an animation
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
UIView *window = [[UIApplication sharedApplication] keyWindow];
UIView *shield = [[UIView alloc] initWithFrame:window.bounds];
shield.backgroundColor = [UIColor blackColor];
shield.alpha = 0.5f;
[window addSubview:shield];
spinner.center = shield.center;
[shield addSubview:spinner];
spinner.hidden = NO;
NSLog( @"JCL.callServerWithRequest(), spinner view: %@, shield view: %@, window: %@", spinner, shield, window );
[spinner startAnimating];
// Hand over to the Runnloop to wait
CFRunLoopRun();
[spinner stopAnimating];
[spinner removeFromSuperview];
[spinner release];
[shield removeFromSuperview];
[shield release];
Это работает нормально, за исключением того, что любые нажатия на кнопки где-то воспроизводятся после загрузки, поэтому, если пользователь нажимает кнопку загрузки дважды, он также выполняет загрузку дважды.
Любая идея, как использовать события пользовательского интерфейса до снятия щита.
Спасибо Энди
2 ответа
Попробуйте, не связываясь с runloops. Я подозреваю, что события пользовательского интерфейса поступают в обычный цикл в окне, но не обрабатываются до тех пор, пока ваш пользовательский цикл не вернется, и в этот момент представление "щит" больше не может их перехватить. Если вы поставите щит на место, а затем позволите главному рупору справиться с вещами, щит должен поймать их всех как обычно.
Благодаря Anomie я наконец-то попытался обойтись без CFRunLoopRun(), и это довольно сложно, потому что выполнение делится на две части: - вызов и возврат результата через обратный вызов. Но затем я выстрелил себе в пресловутую ногу, потому что я пытался заблокировать возвращающийся поток, чтобы замедлить выполнение, которое не работало, потому что это было выполнено снова в основном потоке.
В конце концов я замедлил работу веб-службы, и тогда все заработало как положено.