2013-12-01 2 views
3

В Xcode 5.0.2 я создал пустое приложение Master Detail для iPhone, и это работает хорошо в тренажере:Добавление модального вида нагрузки на Master-Detail применения (в applicationDidBecomeActive метода)

screenshot

Когда приложение iPhone запускается или пробуждается с фона, я хотел бы показать модальное представление с меткой «Загрузка ...» в середине, получить веб-страницу (в этом случае, в реальном приложении это будет быть обновлениями игр и оценками игроков), а затем отказаться от модального представления на завершении выборки веб-страницы или ошибок или тайм-аутов.

Таким образом, я создал 2 новых файла, LoadingViewController.h и LoadingViewController.m (без каких-либо пользовательских кодов от меня пока).

И поскольку это версия Xcode 5, нет файлов xib, но Main.storyboard - поэтому я перетащил контроллер просмотра из библиотеки объектов на раскадровку. Затем на правой стороне я выбрал класс LoadingViewController в качестве пользовательского класса в идентичности инспектора:

screenshot

И, наконец, я добавил 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>. 

ответ

1

Во-первых, когда вы создаете экземпляр контроллера в раскадровке, вы не используете alloc init, вы используете метод UIStoryboard instantiateViewControllerWithIdentifier:. Вам нужно дать вашему контроллеру «Искатель раскадровки», который я вижу на вашем изображении, которого вы еще не сделали (и если вы не понимаете раскадровки, прочитайте документы Apple об этом).

Вы можете отклонить свой модальный вид от обработчика завершения - обработчик - это код, который вызывается после завершения операции async, поэтому вы должны использовать [NSOperationQueue mainQueue] в качестве аргумента очереди.

+0

Не будет использовать '[NSOperationQueue mainQueue]' заморозить мой интерфейс или это только для 'completeHandler'? –

+1

@AlexanderFarber, как говорят документы, «queue» - очередь операций, в которую отправляется блок обработчика, когда запрос завершен или завершился с ошибкой.«Итак, эта очередь предназначена только для блока завершения, асинхронный процесс по-прежнему работает в фоновом потоке. – rdelmar

+0

Спасибо, пожалуйста, вы можете получить совет по моему обновленному вопросу? –

Смежные вопросы