2015-04-01 4 views
1

Эта проблема звучит довольно просто, но я не понимаю, что я пропускаю.Нажатие нового VC в navigationController, кажется, не имеет эффекта

Я пытаюсь вставить новый контроллер вида в контроллер навигации, однако topViewController остается незатронутым.

#import "TNPViewController.h" 
@interface TNCViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout> 

@implementation TNCViewController 

-(void)userDidSelectNewsNotification:(NSNotification*)note 

{ 

    TNPViewController *nextViewController = [[TNPViewController alloc] init]; 

    [[self navigationController] pushViewController:nextViewController animated:YES]; 

    UIViewController *test = [[self navigationController] topViewController]; 

} 

В тесте показан экземпляр TNCViewController вместо TNPViewController. Как это возможно?

UPDATE

Спасибо за участие каждого. Имя метода, указывающее уведомления, является красной селедкой. Я нашел проблему, как ранее упоминал Стюарт, но позже удалил. (Поскольку у меня высокий рейтинг репутации, я все еще могу видеть его удаленное сообщение).

Моя первая испытательная установка была такова:

-(void)testSelectingNewsPushesNewViewController 
{ 
    [viewController userDidSelectNewsNotification:nil]; 
    UIViewController *currentTopVC = navController.topViewController; 
    XCTAssertFalse([currentTopVC isEqual:viewController], @"New viewcontroller should be pushed onto the stack."); 
    XCTAssertTrue([currentTopVC isKindOfClass:[TNPViewController class]], @"New vc should be a TNPViewController"); 
} 

И это не удалось. Затем я установил точку останова и попробовал экземпляр test выше, и он все еще показывал неправильный контроллер topview.

По крайней мере, тест блок работает, если я изменю

[[self navigationController] pushViewController:nextViewController animated:YES]; 

в

[[self navigationController] pushViewController:nextViewController animated:NO]; 

Лучшим решением является использование постоянной анимированный для модульных тестов для отключения анимации.

+2

Пульт управления занимает некоторое время. Он не закончен, когда вы пытаетесь прочитать верхний контроллер. – oxigen

+0

Не было бы разумнее просто добавить следующий контроллер вида на раскадровку и передать его через segues? Затем соответствующим образом измените содержание? Вместо инициализации каждый раз, когда новый TNPViewController ... – Joze

+0

проверяет этот '[self navigationController] .title = @" Some Title ";' Если это не работает, это должно доказать, что ваш пользовательский интерфейс имеет фактически какую-то другую навигацию VC, которая не равна '[self navigationController]' –

ответ

0

Это не отвечает на ваш вопрос о том, почему ваш навигационный контроллер не нажимает ваш VC. Но это предложение о другом возможном подходе.

Вместо этого вы можете добавить новый VC на раскадровки и просто активировать segue при активации метода userDidSelectNewsNotification. Затем измените информацию в соответствии с событием в VC, особенно, поскольку вы все равно инициализируете его каждый раз.

+0

Хотя я согласен с тем, что раскадровки могут быть более удобным способом управления пользовательским интерфейсом приложения, я думаю, вы неправильно поняли, как они работают. Просмотр контроллеров в раскадровках _not_ повторно используется; новый инициализируется каждый раз, когда выполняется сегрегация раскадровки, точно так же, как в программном подходе @ Хомана. На самом деле, это может быть причиной того, что нельзя использовать раскадровки, потому что в коде вы можете хранить и повторно использовать труднодоступные диспетчеры представлений, а не создавать новые экземпляры каждый раз из раскадровки. – Stuart

+0

@Stuart Спасибо за это, да, я, должно быть, неправильно понял их внутреннюю работу. Зависит от его приложения, я думаю. Но это все еще проще в использовании и понимании ИМХО. Однако я вижу преимущество программного подхода. Если он собирается инициализировать его каждый раз, в любом случае segues - это путь. – Joze

0

Это что-то вроде удара в темноте, но проблему трудно диагностировать без дополнительной информации.

Я вижу, что вы пытаетесь нажать новый контроллер представления в ответ на уведомление. Вы уверены, что это уведомление обрабатывается в основном потоке? Методы пользовательского интерфейса, такие как нажатие новых контроллеров представлений, не будут выполняться (или, по крайней мере, вести себя непредсказуемо), когда они не выполняются в основном потоке. Это может также способствовать объяснению нечетного поведения topViewController, возвращающего непредвиденный экземпляр диспетчера. *

В идеале вы должны гарантировать, что эти уведомления размещены в основном потоке, поэтому они будут получены в том же потоке. Если вы не можете гарантировать, что это (например, если вы не несет ответственности за размещение уведомлений в другом месте в коде), то вы должны послать любой UI-кода, связанного с основным потоком:

- (void)userDidSelectNewsNotification:(NSNotification *)note 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     TNPViewController *nextViewController = [[TNPViewController alloc] initWithNibName:@"TNPViewController" bundle:nil]; 
     [self.navigationController pushViewController:nextViewController animated:YES]; 
    }); 
} 

Кроме того, оказывается, вас не инициализируются TNPViewController с использованием назначенного инициализатора (если только в вашем подклассе вы не перекрываете init и звоните туда до initWithNibName:bundle:?). Я бы не ожидал, что это приведет к отказу полностью, но может привести к тому, что ваш контроллер просмотра не будет правильно инициализирован.

В целом, возможно, вам лучше создать контроллеры представлений в раскадровке и использовать segues для выполнения ваших навигационных переходов, как предлагает @Joze в своем ответе. Вы все же можете инициировать эти сценарии раскадровки в коде (например, в ответ на ваше уведомление) с помощью performSegueWithIdentifier:, но опять же, обязательно сделайте это в основном потоке. См. Using View Controllers in Your App для получения более подробной информации об этом подходе.


* Первоначально я написал ответ, пытаясь объяснить неожиданное topViewController значение как результат отсроченных анимированных переходов. Хотя верно, что анимированные переходы отложены, это не мешает topViewController быть установленным на новый контроллер представления сразу.

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