Подтвердить что ты не робот

UINavigationController popToRootViewController, а затем сразу же нажмите новый вид

У меня есть tabBarController с двумя вкладками, первый из которых содержит экземпляр NavigatorController. NavigatorController инициируется с помощью настраиваемого viewController "peersViewController", который отображает все сетевые одноранговые узлы в tableView. При выборе однорангового узла экземпляр "FilesListViewController" (который перечисляет файлы в каталоге c: \) помещается в стек навигационной системы.

В этом файлеListViewController у меня есть кнопка, позволяющая ему перейти в каталог документов. Для этого я подключил интерфейс для вызова метода пути gotoDirectory: (NSString *) в корневом контроллере:

- (void)gotoDirectory:(NSString*)path {
     [[self navigationController] popToRootViewControllerAnimated:YES];
     NSArray *files = [self getFilesFromPeerAtPath:path];
     FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files];
     [[self navigationController] pushViewController:filesVC animated:YES];
     [filesVC release];
}

Однако, когда я нажимаю эту кнопку, диспетчер навигации выводил мое представление на контроллер корневого представления, но затем созданный экземпляр FilesListViewController не появился. Из журнала я знаю, что пользовательский метод initWithFiles действительно был вызван, и сетевые файлы действительно получили имена файлов.

В этом что-то другое. Я попытался щелкнуть вторую вкладку, а затем вернуться к первой вкладке и huala! мне нужны имена файлов. Похоже, что данные и файлыListViewController действительно были введены в стек навигатора, но дисплей не обновился, а застрял на экране rootViewController (peersViewController).

Я делаю что-то неправильно?

-. Бен

- Отредактировано через 15 минут после публикации вопроса. Я нашел обходное решение, но это беспокоит меня, что поп, а затем нажмите не работает.

- (void)gotoDirectory:(NSString*)path {
     PeersListViewController *rootViewController = (PeersListViewController*)[[[self navigationController] viewControllers] objectAtIndex:0];
     [[self navigationController] setViewControllers:[NSArray arrayWithObject:rootViewController]];
     FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files];
     [[self navigationController] pushViewController:filesVC animated:YES];
     [filesVC release];
}

Похоже, что navigationController должен быть обойден таким образом, и мне, вероятно, придется выпустить все viewControllers, которые были в исходном стеке. Однако это работает на симуляторе iphone 3.0.

Если я использую этот код, как это сделать, как следует освобождать память? должен ли я получить исходный NSArray контроллеров view и освободить все?

4b9b3361

Ответ 1

Проблема и решение этой проблемы на самом деле чрезвычайно просто.

Вызов [self.navigationController popToRootViewControllerAnimated:YES] устанавливает self.navigationController в nil. Когда вы впоследствии вызываете [self.navigationController pushViewController:someOtherViewController], вы эффективно отправляете сообщение в nil, которое ничего не делает.

Чтобы обходной путь, просто настройте локальную ссылку на navigationController и используйте это вместо:

UINavigationController * navigationController = self.navigationController;
[navigationController popToRootViewControllerAnimated:NO];
[navigationController pushViewController:someOtherViewController animated:YES];

Как указано Джейсоном, popToRootViewController должен выполняться без анимации, чтобы это работало правильно.

Благодарим вас за jpimbert на форумах Apple, указав это.

Ответ 2

У меня очень похожая проблема (но без использования вкладки).

У меня есть три viewController: main (root), форма и результат. когда стек UINavigationController

"main → result"

на btnClick я делаю popToRootViewControllerAnimated, затем нажмите formViewCtrl. чтобы иметь

"main → form"

Значок заголовка навигационной панели и обратной кнопки верны и вызывается событие formViewCtrl. НО, я все еще вижу основной вид.

Вот мое "решение"

После выполнения какого-то теста я обнаружил, что без анимации перейти к rootViwCtrl этой работе отлично. Поэтому я использую анимацию только для того, чтобы нажимать viewCtrl.

iPhone 3.0, проблема найдена на устройстве и симуляторе.

Если у меня есть что-то новое, я буду обновлять/комментировать мой пост.

Ответ 3

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

В Xcode 4 у вас есть раскадровка. Скажем, у вас есть эти контроллеры представлений: HomeViewController, FirstPageViewController, SecondPageViewController. Обязательно нажмите на каждый из них и назовите их идентификаторы, перейдя в панель "Утилиты" → "Инспектор атрибутов". Мы скажем, что они называются Home, First и Second.

Вы являетесь домом, затем переходите к First, затем вы хотите, чтобы вы могли перейти на Second и иметь возможность нажать кнопку "Назад", чтобы вернуться в Home. Для этого вы хотите изменить свой код в FirstPageViewController.

Чтобы расширить пример, сделайте кнопку в FirstPageViewController в раскадровке. Ctrl-перетащите эту кнопку в FirstPageViewController.m. В этом случае следующий код достигнет желаемого результата:

    // Remember to add #import "SecondPageViewController.h" at the top
    SecondPageViewController *secondView = [self.storyboard instantiateViewContorllerWithIdentifier:@"Second"];
    UINavigationController *navigationController = self.navigationController;
    NSArray *array = [navigationController viewControllers];
    // [array objectAtIndex:0] is the root view controller
    NSArray *viewControllersStack = [NSArray arrayWithObjects:[array objectAtIndex:0], secondView, nil];
    [navigationController setViewControllers:viewControllersStack animated:YES];

В принципе, вы захватываете контроллеры представлений, упорядочиваете их в стеке в том порядке, в котором хотите, а затем используя навигационный контроллер, используйте этот стек для навигации. Это альтернатива толчкам и выскакиванию.

Ответ 4

Я нашел обходной путь, но я не могу объяснить, почему он работает: 1. Сначала нажмите необходимый контроллер. 2. Затем нажмите на тот, который вы хотите.

Это совершенно нелогично, но это работает для моего дела. Для того, чтобы все было ясно, я использую его в следующем сценарии: Первый экран → Переход к экрану загрузки → Второй экран Когда я нахожусь на втором экране, я не хочу иметь экран загрузки в стеке, и когда я вернусь, я должен перейти на первый экран.

С уважением, Веско Колев

Ответ 5

Ответ на Nick Street отлично работает, если вы хотите popToRootViewController и затем нажмите другой VC.

VC1 → VC2 → VC3: нажмите кнопку возврата с VC3 = > VC2, затем VC1, здесь OK

Однако, когда VC1 толкает VC2, который, в свою очередь, подталкивает VC3, то возврат к VC1 непосредственно из VC3 не работает по желанию:

Я реализовал в VC3 -(void)viewWillDisappear:(BOOL)animated:

-(void)viewWillDisappear:(BOOL)animated{

    ...
    [self.navigationController popToRootViewControllerAnimated:YES];
}

Я также попытался реализовать его в кнопке "Назад", тот же результат: при нажатии кнопки "Назад" из VC3, чтобы вернуться к VC1: он ломается. Фактический VC - VC1, но панель навигации по-прежнему VC2. Играя с другими комбинациями, я получаю VC1 navBar на VC2. Общий беспорядок.

Лода упомянул о сроках. Я думаю, что главная проблема здесь. Я пробовал несколько вещей, так что, может быть, я что-то упустил, но вот что мне помогло, наконец:

В VC3:

-(void)viewWillDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];
    // notify VC2
    [[NSNotificationCenter defaultCenter] postNotificationName:backFromV3 object:self];
}

В VC2:

-(void)viewDidLoad {

    ...

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(backFromV3)
                                                 name:@"BackFromV3"
                                               object:nil];
}

-(void)backFromV3{
    [NSTimer scheduledTimerWithTimeInterval:0.5 
                                 target:self
                               selector:@selector(backToRootViewController)
                               userInfo:nil
                                repeats:NO];
}

-(void)backToVC1 {
    self.navigationItem.rightBarButtonItem = nil;
    [self.navigationController popToRootViewControllerAnimated:YES];
}

Конечно, сделайте необходимую очистку.

Здесь важна таймер. Если 0, он ломается. 0.5, похоже, в порядке.

Это отлично работает для меня. Немного тяжело, но я не смог найти ничего, что могло бы сделать трюк.

Ответ 6

Фактически вы можете сохранить анимацию "Назад", а затем анимацию "Вперед", в основном задерживая анимацию push до завершения поп-анимации. Вот пример:

(Примечание. У меня есть переменная NSString, называемая "transitionTo" в моем приложении appDelegate, которая первоначально была установлена ​​на @"")... Сначала установите эту переменную в NSString, которую вы можете обнаружить позже. Затем вытащите контроллер, чтобы дать вам хороший переход на экран к корню:

appDelegate.transitionTo = @"Another";
[detailNavigationController popToRootViewControllerAnimated:YES];

Затем внутри класса rootviewcontroller используйте метод viewDidAppear:

-(void)viewDidAppear:(BOOL)animated
{
    AppDelegate *appDelegate =(AppDelegate*) [UIApplication sharedApplication].delegate;
    if([appDelegate.transitionTo isEqualToString:@"Another"])
    {
        [self transitionToAnotherView];
        appDelegate.transitionTo = @"";
    }
}

-(void)transitionToAnotherView
{
    // Create and push new view controller here
    AnotherViewController *controller = [[AnotherViewController alloc] init];

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Home" style:UIBarButtonItemStyleBordered target:nil action:nil];
    [self.navigationItem setBackBarButtonItem:backButton];

    [[self navigationController] pushViewController:controller animated:YES];
}

Итак, в основном, поп в корень... когда переход заканчивается на "viewDidAppear"... затем нажмите следующий вид. Мне удалось сохранить переменную, чтобы указать вам, с каким видом вы хотите перейти (с @", что означает не делать переход в случае, когда я хочу остаться на этом экране).