2013-05-13 4 views
1

Просто для изучения некоторых аспектов xCode я создаю простое приложение с 2 функциональными контроллерами. Каждый из них содержит кнопку, которая может быть нажата для переключения на другую. Я не использую segues. Я использую указатели, извлеченные из делегата приложения.просмотр контроллеров: презентация, увольнение

визуальная иллюстрация (нажмите для более высокого разрешения): visual

Когда приложение загружает контроллер вида корня представляет вид 1. При нажатии кнопки «переключатель для просмотра 2,» следующий код вызывает вид-появляться :

- (IBAction)buttonPressed:(id)sender 
{ 
    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 
    [self presentViewController:appDelegate.view2 animated:YES completion:nil]; 
} 

Пока что так хорошо.

Но при нажатии кнопки «переключатель для просмотра 1» на второй взгляд, это тот же самый код (вместо «view2» с «view1») дает следующее сообщение об ошибке:

Применение пытались представить модально активный контроллер.

Итак, подведем итог (где -> = подарки), мы имеем корень -> view1 -> view2 -x-> view1

Я не забочусь о сохранении истории о том, кто представляет кого. Я просто хочу, чтобы кнопки отображали верхний (видимый) ранее отображаемый контроллер представлений, сохраняя состояние его представлений.

Было бы неплохо знать следующее:

  1. Есть обходной путь, который позволил бы мне достичь намеченного поведения, используя presentViewController? Например, корень -> вид2 -> вид1

  2. Какие другие методы были бы более практичными для достижения желаемого поведения? Он/они должны использовать делегат приложения, потому что в моем реальном приложении это неизбежно.

  3. Я нарушаю правила, пытаясь установить контроллер сверху, не интегрируя его в какую-то более крупную архитектуру? Например, это поведение, которое, как предполагается, должно обрабатывать навигаторы и нажатие/выскакивание? Если да, можете ли вы объяснить, почему xCode не хочет, чтобы я это делал? Почему я не могу просто отобразить любой контроллер вида, который я хочу, без необходимости иметь какое-либо отношение к другим контроллерам представлений? (Может быть, потому что это может привести к злоупотреблению делегатом приложения?)

  4. Что это означает «представить» контроллер вида? Какие функциональные ограничения или возможности он влечет за собой создание указателей между презентацией и презентатором? Какова важность того, чтобы оставить контроллер представления «активным»?

  5. Если вместо этого сделать кнопку в представлении1, отправьте сообщение presentViewController в корневой вид (который, я надеюсь, просто изменит цепочку представлений от root -> view1 до root -> view2, оставив view1 все еще существующим в памяти, но не часть этой цепочки), я получаю другую ошибку: «Попытайтесь представить, чья точка зрения не в иерархии окон!» Что это значит? Я не могу найти объяснение иерархии окон.

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

ответ

3

Правильный способ сделать это, чтобы получить основной rootVC, чтобы сделать презентацию и отклонить (как вы пытаетесь - без увольнения - в пункте 5). Вы можете добиться этого, отправив сообщение + блок завершения обратно в rootVC из каждого из view1 и view2, когда вы хотите представить другой.

Когда вы находитесь в view1:

- (IBAction)buttonPressed:(id)sender 
    AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 

    UIViewController* presentingVC = self.presentingViewController; 
    [presentingVC dismissViewControllerAnimated:YES completion:^{ 
      [presentingVC presentViewController:appDelegate.view2 
            animated:YES 
            completion:nil]; 
    }]; 
} 

и аналогично для View2. Позаботьтесь, что вам нужна эта строка:

 UIViewController* presentingVC = self.presentingViewController; 

, как вы не можете обратиться к «» self.presentingViewController внутри блока завершения, как это контроллер был удален с поля в этой точке.

Я думаю, что ответы пункты 1 и 2.

Чтобы ответить на пункт 3 «Почему я не могу просто отобразить любой вид контроллера я хочу, без него обязательно должен иметь какие-либо отношения с другими контроллерами зрения?» - ну вы можете (через свойство rootViewController окна), но тогда вам вам придется реализовать навигацию и управлять своими указателями viewController, а это значит, что вы в конечном итоге создадите какой-то контроллер. Apple помогает вам здесь, предоставляя вам несколько, которые охватывают большинство потребностей.

Что касается вашей точки 4 - представление viewController контролируется представляющим VC, поэтому вы хотите сохранить его «активным». Когда вы отправите это сообщение: [self dismissViewControllerAnimated:completion:], self просто перенаправляет сообщение в его presentingViewController. Если вы избавитесь от своего presentingViewController, ваш метод увольнения сломается.

Пункт 5 ответа выше. Сначала вы должны сначала снять верхний вид, прежде чем задавать основной взгляд на презентацию.Обратите внимание, что view1 «все еще в памяти», но только потому, что вы сохранили указатель на него в своем делете приложения.

обновление

Как вы пытаетесь получить эту работу с начального запуска, прямо к view1, вы могли бы сделать свойство BOOL launched и проверить/установить его с вашего RootViewController-х viewDidAppear:

- (void) viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
    if (!self.launched) { 
     self.launched = TRUE; 
     AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; 
     [self presentViewController:appDelegate.view1 
          animated:YES 
         completion:nil]; 
    } 
} 
+0

Спасибо, спасибо. Понял. Примеры кода и явные ссылки на имена свойств/методов настолько полезны. – mkc842

+0

Однако есть сбой - что-то о попытке отображения viewControllers в слишком быстрой последовательности. Нажатие «для просмотра 2» запускает анимацию, но остается на вид 1. Сообщение об увольнении дает следующее: «Неуравновешенные вызовы для перехода на начало/конец перехода для ». Сообщение презентации дает следующее: «Предупреждение: попытайтесь представить в во время презентации!" – mkc842

+0

@ mkc842 - Мое решение должно (отлично) работать как с анимацией, так и с анимацией. Попробуйте запустить с анимацией, установленной в НЕТ, посмотрите, какое сообщение вы получите. Проверьте код, чтобы убедиться, что ничего не запускается, когда вы нажимаете кнопки «Просмотреть ...». Пройдите код в отладчике, чтобы увидеть, где именно происходит ошибка. Если вы все еще застряли, отправляйте точное сообщение об ошибке здесь. – foundry

1

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

1) Нет, вы не должны делать все это с помощью currentViewController.

2) Если вы хотите сделать root -> view1 -> view2 -> view1, то вы не будете делать все с помощью currentViewController. Чтобы перейти от view1 к view2, вы должны использовать функцию rejectViewControllerAnimated: завершение.

3) Контроллеры представлений имеют отношения, когда вы используете presentViewController: анимированные :. Представляющий контроллер имеет указатель на тот, который он представляет, и представленный имеет указатель на тот, который его представил. Итак, вы получаете эти отношения, хотите ли вы этого или нет. Существует способ отобразить любой контроллер, который вам нужен, без отношения между ними - просто перезагрузите контроллер корневого окна окна. Старый диспетчер представлений будет освобожден (если вы не сохраните сильный указатель на него), а новый станет контроллером корневого представления окна.

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

5) Вы получаете эту ошибку, поскольку вид корня отсутствует на экране, а view1 is is. Вам нужно представить контроллер контроллера с экрана на экране.

+0

Спасибо, это полезно. Он просто прошел лишнюю милю :) – mkc842

+0

Привет, rdelmar. Я видел ваши ответы на несколько вопросов о просмотре контейнеров, и вы, кажется, много разбираетесь в этой теме. Вы могли бы помочь мне с этим вопросом? http://stackoverflow.com/questions/16661240/cant-make-tab-bottom-bar-hidden-when-using-container-views#comment23990352_16661240 Спасибо! – mkc842

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