В Xcode 5.0.2 я создал пустое приложение Master Detail для iPhone, и это работает хорошо в тренажере:Добавление модального вида нагрузки на Master-Detail применения (в applicationDidBecomeActive метода)
Когда приложение iPhone запускается или пробуждается с фона, я хотел бы показать модальное представление с меткой «Загрузка ...» в середине, получить веб-страницу (в этом случае, в реальном приложении это будет быть обновлениями игр и оценками игроков), а затем отказаться от модального представления на завершении выборки веб-страницы или ошибок или тайм-аутов.
Таким образом, я создал 2 новых файла, LoadingViewController.h и LoadingViewController.m (без каких-либо пользовательских кодов от меня пока).
И поскольку это версия Xcode 5, нет файлов xib, но Main.storyboard - поэтому я перетащил контроллер просмотра из библиотеки объектов на раскадровку. Затем на правой стороне я выбрал класс LoadingViewController в качестве пользовательского класса в идентичности инспектора:
И, наконец, я добавил 3 метода к AppDelegate.m:
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[self showLoadingView];
}
- (void)applicationWillResignActive:(UIApplication *)application
{
[self dismissLoadingView];
}
- (void)showLoadingView
{
NSLog(@"%s", __PRETTY_FUNCTION__);
[self fetchHttp];
LoadingViewController *other = [[LoadingViewController alloc] init];
[self.window.rootViewController presentViewController:other animated:YES completion:nil];
}
- (void)dismissLoadingView
{
NSLog(@"%s", __PRETTY_FUNCTION__);
[self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)fetchHttp
{
NSLog(@"%s", __PRETTY_FUNCTION__);
NSString *urlAsString = @"http://stackoverflow.com";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] > 0 &&
error == nil) {
NSString *html = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"HTML = %u", [html length]);
}
else if ([data length] == 0 &&
error == nil) {
NSLog(@"Nothing was downloaded.");
}
else if (error != nil) {
NSLog(@"Error happened = %@", error);
}
// XXX how to dismiss the modal view here, it's a different thread?
}];
}
К сожалению теперь я получаю черный экран в симуляторе и следующий выход:
2013-12-01 22:37:01.332 LoadingTest[3840:a0b] -[AppDelegate showLoadingView]
2013-12-01 22:37:01.334 LoadingTest[3840:a0b] -[AppDelegate fetchHttp]
2013-12-01 22:37:01.857 LoadingTest[3840:a0b] Unbalanced calls to begin/end appearance transitions for <UINavigationController: 0x8c74f10>.
2013-12-01 22:37:01.870 LoadingTest[3840:4607] HTML = 196885
Мне трудно понять , как использовать раскадровку здесь (и я хотел бы использовать его, если это возможно) - потому что книги, которые я читаю (в O'Reilly Safari), все говорят о файлах xib (возможно, для старых версий Xcode?).
А также я не понимаю, как отменить модальный вид из моего завершенияHandler, поскольку он находится в другом потоке, и я, вероятно, не должен называть dismissViewControllerAnimated
оттуда?
UPDATE:
Я добавил "раскадровки ID" на мой взгляд: loadingView
и следующий код для AppDelegate.m
:
- (void)showLoadingView
{
NSLog(@"%s", __PRETTY_FUNCTION__);
[self fetchHttp];
UIStoryboard *board = [self.window.rootViewController storyboard]; //[UIStoryboard storyboardWithName:@"Main.storyboard" bundle:nil];
LoadingViewController *other = [board instantiateViewControllerWithIdentifier:@"loadingView"];
[self.window.rootViewController presentViewController:other animated:YES completion:nil];
}
- (void)fetchHttp
{
NSLog(@"%s", __PRETTY_FUNCTION__);
NSString *urlAsString = @"http://stackoverflow.com";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] > 0 &&
error == nil) {
NSString *html = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"HTML = %u", [html length]);
}
else if ([data length] == 0 &&
error == nil) {
NSLog(@"Nothing was downloaded.");
}
else if (error != nil) {
NSLog(@"Error happened = %@", error);
}
[self dismissLoadingView];
}];
}
, но теперь я получаю предупреждение ниже и loadingView
(вероятно, из-за того, что веб-страница загружается быстрее, чем отображается модальный вид?):
2013-12-03 01:49:12.208 LoadingTest[631:70b] -[AppDelegate showLoadingView]
2013-12-03 01:49:12.210 LoadingTest[631:70b] -[AppDelegate fetchHttp]
2013-12-03 01:49:12.756 LoadingTest[631:70b] HTML = 200949
2013-12-03 01:49:12.757 LoadingTest[631:70b] -[AppDelegate dismissLoadingView]
2013-12-03 01:49:12.757 LoadingTest[631:70b] Warning: Attempt to dismiss from view controller <UINavigationController: 0x8a70ce0> while a presentation or dismiss is in progress!
2013-12-03 01:49:12.844 LoadingTest[631:70b] Unbalanced calls to begin/end appearance transitions for <UINavigationController: 0x8a70ce0>.
Не будет использовать '[NSOperationQueue mainQueue]' заморозить мой интерфейс или это только для 'completeHandler'? –
@AlexanderFarber, как говорят документы, «queue» - очередь операций, в которую отправляется блок обработчика, когда запрос завершен или завершился с ошибкой.«Итак, эта очередь предназначена только для блока завершения, асинхронный процесс по-прежнему работает в фоновом потоке. – rdelmar
Спасибо, пожалуйста, вы можете получить совет по моему обновленному вопросу? –