ПРИМЕЧАНИЕ: это было написано в 2013 году. Изменения в способе работы iOS с представлениями иерархий в настоящее время могут сделать это решение бесполезным и / или опасным. Так что используйте на свой страх и риск.
Оригинальный ответ
При вложении пользовательского UIViewController в UINavigationController методы viewWillAppear и viewDidAppear пользовательского viewController могут не вызываться в зависимости от сложности иерархии контроллера представления (например, модальные представления, контроллер навигации внутри контроллера представления вкладок ...). Итак, если вы окажетесь в такой ситуации, что вы можете сделать, чтобы эти два метода были вызваны?
Ответ ...
Используйте методы UINavigationControllerDelegate
Это очень элегантный метод для реализации, поскольку он не основывается на каких-либо предположениях относительно того, когда контроллер будет загружен навигационным контроллером.
Доступны два метода:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
Вот как изменится код.
Вам необходимо объявить, что ваш CustomViewController реализует протокол UINavigationControllerDelegate:
@interface CustomViewController : UIViewController <UINavigationControllerDelegate>
Вам необходимо установить свой CustomViewController в качестве делегата UINavigationController, в котором вы его инициализируете.
Наконец, вы также должны добавить свою собственную реализацию методов UINavigationControllerDelegate в реализацию класса CustomViewController. Например, вы можете реализовать метод navigationController:willShowViewController:animated:
, чтобы:
- когда UINavigationController собирается показать сам контроллер представления, ваш метод viewWillAppear называется
- когда UINavigationController собирается показать другой контроллер представления, делегат UINavigationController устанавливается на этот другой контроллер представления, при условии, что этот контроллер представления реализует метод UINavigationViewControllerDelegate.
Элемент списка
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([viewController isEqual:self]) {
[viewController viewWillAppear:animated];
} else if ([viewController conformsToProtocol:@protocol(UINavigationControllerDelegate)]){
// Set the navigation controller delegate to the passed-in view controller and call the UINavigationViewControllerDelegate method on the new delegate.
[navigationController setDelegate:(id<UINavigationControllerDelegate>)viewController];
[[navigationController delegate] navigationController:navigationController willShowViewController:viewController animated:YES];
}
}
И navigationController:didShowViewController:animated:
можно реализовать просто следующим образом:
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
if ([viewController isEqual:self]) {
[self viewDidAppear:animated];
}
}
Преимущество этого подхода состоит в том, что вы полагаетесь исключительно на то, как должен работать UINavigationViewController, и вы делаете свои звонки как раз в нужное время. Это также позволяет передавать делегирование при перемещении вверх и вниз по иерархии контроллера навигации непосредственно перед вызовом метода viewWillAppear.
Опять же для простой иерархии это может не потребоваться. Но если вы когда-нибудь окажетесь в ситуации, когда ваши методы viewWillAppear
и viewDidAppear
не будут вызваны, вы теперь знаете, что делать ...