Search code examples
iosswiftstoryboardmkmapviewmapbox

IBOutlet variables return nil when I try to access them. Error: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value


I have a UIViewController that implements MGLMapViewDelegate. I'm trying to place a nav bar at the top, with two buttons.

I couldn't get my buttons or nav bar visible so I tried using the function view.bringSubviewToFront() within my viewDidLoadFunction() as suggested on this post

When I did this, I received the error

Error: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

I don't understand how the IBOutlet variables can ever be nil, I thought they were assigned to the storyboard buttons


My ViewController Class(At least the parts that I think are important)

class ViewController: UIViewController, MGLMapViewDelegate {

...

var mapView: MGLMapView?
@IBOutlet var navBar: UINavigationBar!
@IBOutlet var signOutButton: UIButton!
@IBOutlet var newPostButton: UIButton!

...

override func viewDidLoad() {
            super.viewDidLoad()

    self.mapView = MGLMapView(frame: view.bounds, styleURL: MGLStyle.lightStyleURL)

    ...

        view.addSubview(self.mapView!)

        view.addSubview(navBar)
        view.addSubview(signOutButton)
        view.addSubview(newPostButton)
        //Make the navBar and Buttons visible
        view.bringSubviewToFront(self.navBar)
        view.bringSubviewToFront(self.signOutButton)
        view.bringSubviewToFront(self.newPostButton)

        ...
}

...

@objc func handleLogout() {
     let loginController = SignInViewController()

     do {
          try Auth.auth().signOut()
      } catch let logoutError {
          print(logoutError)
      }

      present(loginController, animated: true, completion: nil)
  }
}

Some screenshots of my storyboard I thought might be important

enter image description here enter image description here enter image description here enter image description here enter image description here

I've tried placing this in my view controller right after super.viewDidLoad()

self.storyboard?.instantiateViewController(withIdentifier: "mainViewController") as! ViewController

I've tried bringing the view to the front of the mapview instead of the main view

self.mapView.bringViewToFront(navBar)

I've tried placing the code inside functions like awakeFromNib and viewDidLayoutSubviews

    override func awakeFromNib() {
        super.awakeFromNib()

        //Make the navBar and Buttons visible
        self.mapView!.bringSubviewToFront(self.navBar)
        self.mapView!.bringSubviewToFront(self.signOutButton)
        self.mapView!.bringSubviewToFront(self.newPostButton)

    }

Solution

  • From your comments, I understood that you are instantiating the controller wrongly.

    let mainController = ViewController(). // Wrong
    

    This will just instantiate the ViewController but not any objects from the story board.

    Use below code to instantiate viewcontroller from storyboard.

        if let vc = self.storyboard?.instantiateViewController(withIdentifier: "mainViewController") as? ViewController {
            //Set any data if required, then present
            self.present(vc, animated: true, completion: nil)
        }
    

    If you use multiple storyBoards,

     let storyboard = UIStoryboard(name: "Main", bundle: nil)
     if let vc = storyboard.instantiateViewController(withIdentifier: "mainViewController") as? ViewController {
            self.present(vc, animated: true, completion: nil)
       }