簡體   English   中英

使用 UINavigationController 時,不會調用控制器的 viewWillAppear 或 viewDidAppear 方法

[英]When using a UINavigationController the viewWillAppear or viewDidAppear methods of my controller are not called

這里是球場。

  • 我有一個 UIViewController 子類,它在其 viewWillAppear 和 viewDidAppear 方法中執行某些操作。
  • 我想將此視圖控制器嵌套在 UINavigationViewController 中。
  • 根據視圖層次結構的復雜性,我的控制器的兩個方法viewWillAppearviewDidAppear可能不會被調用。

我應該怎么做才能確保無論我的視圖層次結構如何都始終調用這兩個方法?

“復雜”視圖層次結構的示例:

UIViewController subclass containing a UITabBarController
     |_ Each tab containing a UINavigationViewController
         |_ Each UINavigationController controller containing a custom UIViewController

當您將 TabBarController 作為模式視圖呈現時,將調用 TabBarController 的viewWillAppearviewDidAppear方法,但不會調用嵌套在 UINavigationViewControllers 下的自定義 UIViewControllers 的方法。

注意:這是在 2013 年編寫的。如今對 iOS 處理視圖層次結構方式的更改可能會使此解決方案變得無用和/或危險。 所以使用風險自負。

原始答案當在 UINavigationController 下嵌套自定義 UIViewController 時,可能不會調用自定義 viewController 的 viewWillAppear 和 viewDidAppear 方法,具體取決於您的視圖控制器層次結構的復雜性(想想模態視圖、選項卡視圖控制器內的導航控制器......)。 因此,如果您發現自己處於這種情況,您可以做些什么來確保調用這兩個方法?

答案...

使用 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 方法之前在導航控制器層次結構中上下移動時傳遞委托。

同樣對於簡單的層次結構,這可能不是必需的。 但是,如果您發現自己的viewWillAppearviewDidAppear方法未被調用,那么您現在知道該怎么做...

發生這種情況的一個原因是,如果您在UINavigationController子類中覆蓋viewDidAppear:並且不調用[super viewDidAppear:animated]; ...

現在是 2015 年,您可能不需要像接受的答案那樣使用 UINavigationControllerDelegate 方法。 如果您有任何拼寫錯誤或復制/粘貼錯誤,請仔細檢查您的代碼。

我最近遇到了一個問題,即在某些復制/粘貼后不再調用viewDidAppear 閱讀@Yar 的回答后,我在我的代碼中對viewDidAppear進行了搜索,發現[super viewDidAppear:animated]; viewWillAppear被錯誤調用:

-(void)viewWillAppear:(BOOL)animated
{
   [super viewDidAppear:animated];
   //...      ^^^ 
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    // this is never called :(
}

只需在此處分享此發現,以防人們遇到相同的問題。

上述解決方案對我不起作用。 我的情況是嵌套在復雜 UINavigationController 下的自定義視圖控制器不會被稱為 viewWillAppear 和 viewDidAppear。 在自定義視圖控制器中使用以下內容:

beginAppearanceTransition(true, animated: animated)  // Tells a child controller its appearance is about to change. Do not invoke viewWillAppear(_:), viewWillDisappear(_:), viewDidAppear(_:), or viewDidDisappear(_:) directly.
endAppearanceTransition() // Tells a child controller its appearance has changed.

我的問題僅與此類似。

CustomTabBarController -> CustomUINavigationController -> RootViewcontroller

除非您切換到另一個選項卡並返回,否則不會調用 CustomUINavigationController 和 RootViewController 的 viewWillAppear。

解決方法是調用 super.viewWillAppear(animated: true)

override func viewWillAppear(_ animated: Bool) {
    **super.viewWillAppear(true)**
}

為了這個小錯誤,我掙扎了一天多。

應按如下方式進行:

見 (*1) 編輯

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    CustomViewController *controller = [[CustomViewController alloc] initWithNibName:nil bundle:nil];
    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:controller];
    [controller release];

    self.window.rootViewController = navController; //(*1)
    [self.window makeKeyAndVisible];
    [navController release];
    return YES;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM