Xamarin.iOS UINavigationController not being set from code.

Robert McArthur 36 Reputation points
2021-02-14T20:57:46.267+00:00

Good Day,

I have the latest VS2019 for Mac installed with the latest updates. When override the rootviewcontroller everything seems fine. Built standard single view xamarin.ios app... and inserted a NavigationController.

    [Export("window")]
    public UIWindow Window { get; set; }

    [Export("application:didFinishLaunchingWithOptions:")]
    public bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
    {
        // Override point for customization after application launch.
        // If not required for your application you can safely delete this method
        Window = new UIWindow(UIScreen.MainScreen.Bounds);
        UIViewController controller = UIStoryboard.FromName("Main", null).InstantiateInitialViewController() as UIViewController;
        UINavigationController navController = new UINavigationController(controller);


        Window.RootViewController = navController;

        Window.MakeKeyAndVisible();

        application.KeyWindow.RootViewController = navController;

        return true;
    }

However, when I try and access the NavigationController from the Default View Controller it is null.

public partial class ViewController : UIViewController
{
    public ViewController(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        // Perform any additional setup after loading the view, typically from a nib.

        if (NavigationController is null)
            lblNavControllerInfo.Text = "None";
    }

    public override void DidReceiveMemoryWarning()
    {
        base.DidReceiveMemoryWarning();
        // Release any cached data, images, etc that aren't in use.
    }
}

This used to work... what am I doing wrong?

Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,364 questions
0 comments No comments
{count} votes

Accepted answer
  1. Cole Xia (Shanghai Wicresoft Co,.Ltd.) 6,751 Reputation points
    2021-02-15T01:49:45.11+00:00

    Hello,

    Welcome to Microsoft Q&A!

    Try to access the NavigationController from ViewWillLayoutSubviews method .

       public override void ViewWillLayoutSubviews()  
               {  
                   base.ViewWillLayoutSubviews();  
         
                   if (NavigationController is null)  
                       lblNavControllerInfo.Text = "None";  
               }  
    

    Update

    From iOS 13 , we need to duplicate the code into SceneDelegate.
    Check https://stackoverflow.com/a/58405507/8187800 .


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


1 additional answer

Sort by: Most helpful
  1. Robert McArthur 36 Reputation points
    2021-02-15T22:46:08.857+00:00

    ColeXia,

    Firstly, the code that used to work for me didn't have modern iOS SceneDelegate functionality. Something definitely has changed with the current version of Xamarin iOS / VisualStudio. I ended up putting my code that used to work in the AppDelegate (many examples of this on the web) into the SceneDelegate.cs WillConnect Method and I can override the storyboard with a navigation control via code again. The Scene functionality seems to have changed AppDelegate functionality. It seems that the scenedelegate supersedes and ignores any creation of a new window creation in the AppDelegate FinishedLaunching Method. As you can see below, I am not creating a new UIWindow, as it is already created at this point in the screnedelegate lifecycle. Any insight on the change in this functionality would be appreciated.

    [Register("SceneDelegate")]
    public class SceneDelegate : UIResponder, IUIWindowSceneDelegate
    {
    
        [Export("window")]
        public UIWindow Window { get; set; }
    
        [Export("scene:willConnectToSession:options:")]
        public void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions)
        {
            // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
            // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
            // This delegate does not imply the connecting scene or session are new (see UIApplicationDelegate `GetConfiguration` instead).
    
            UIViewController viewController = UIStoryboard.FromName("Main", null).InstantiateViewController("ViewController") as UIViewController;
    
            UINavigationController navController = new UINavigationController(viewController);
    
            this.Window.RootViewController = navController;
    
        }
    
    1 person found this answer helpful.

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.