0

Im working on a messaging app atm and on the ChatView screen where you can see the thread of messages passed between users, I want to give my users the ability to visit the profile of the user they're communicating with.

To get to the ChatView class, a user selects another user to message from the list users. Once that user is selected, a segue to ChatView is happened where the user is initialized. from that view, the user can select the navigation title that displays the name of the person they're chatting with to view their profile. To pass the user data over to the next view controller, I've done this:

// line inside another function setting up the navigation title
    let button =  UIButton(type: .custom)
            button.frame = CGRect(x: 0, y: 0, width: 100, height: 30)
            button.titleLabel?.textColor = .white
            button.setTitle(self.otherUser.name, for: .normal)
            button.addTarget(self, action: #selector(showUserProfile), for: .touchUpInside)
            navigationItem.titleView = button
    
    @objc func showUserProfile() {
            let viewUserProfile = ViewProfileViewController()
            viewUserProfile.user = self.otherUser
            navigationController?.pushViewController(viewUserProfile, animated: true)
        }

However, when I try this out, I get this error: (11db) Unexpectedly found nil while implicitly unwrapping an Optional value, on the Users Profile page, and the app closes. What am I doing wrong here?

HangarRash
  • 7,314
  • 5
  • 5
  • 32
Vandal
  • 708
  • 1
  • 8
  • 21
  • Which line of code exactly is causing the error? – HangarRash Feb 27 '23 at 18:20
  • Most likely a duplicate of [What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – HangarRash Feb 27 '23 at 18:21
  • I guess, that `ViewProfileViewController` has a Storyboard file, or a Xib, and some `IBOutlet`, and that `ViewProfileViewController()` is then not initiliazing it with the associated Storyboard/Xib ? – Larme Feb 27 '23 at 19:00
  • Yes thats what going on I beleive @Larme – Vandal Feb 27 '23 at 22:19
  • Does this answer your question? [Instantiate and Present a viewController in Swift](https://stackoverflow.com/questions/24035984/instantiate-and-present-a-viewcontroller-in-swift) – Larme Feb 27 '23 at 22:44

1 Answers1

0

How does your ViewProfileViewController define its views? If it uses a storyboard or nibfile then loading it with the default initializer won't work. (All of its IBOulets will be nil since it doesn't load its views.)

The usual way to load a view controller from a storyboard is to call the Storyboard's instantiate() method using a string identifier.

The only way calling ViewProfileViewController() will work is if your view controller builds its view hierarchy in its loadView() method.

—-

Edit

If your view controller is defined in a storyboard, you need to:

  1. Instantiate your view controller using func instantiateViewController(withIdentifier identifier: String) -> UIViewController
  2. Present the view controller (modally, by pushing onto your view controller stack, or whatever is appropriate)
  3. Implement the UIViewCotroller method prepare(for:sender:). In that method, pass any data you need to pass into your destination view controller.
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • *"if your view controller builds its view hierarchy in its loadView() method"* - `viewDidLoad` works too. – HangarRash Feb 27 '23 at 19:54
  • @HangarRash No it doesn't. If your view controller loads its view hierarchy from a storyboard, creating a view controller by calling its default initializer will not load the views and connect the outlets. Since outlets are usually implicitly unwrapped optionals, your code then crashes when it tries to reference any of those outlets. – Duncan C Feb 27 '23 at 20:34
  • I was quoting the case (your last paragraph) where you don't use a storyboard. – HangarRash Feb 27 '23 at 20:36
  • This makes sense! ViewProfileViewController uses Storyboard, so I believe that what your pointing out is right. How do I assign a variable to the view controller following this method? @HangarRash – Vandal Feb 27 '23 at 22:19
  • Oh, you mean if you load your view hierarchy in viewDidLoad? That's an anti-pattern. Read the description of loadView(). It is intended for creating your view hierarchy in code, and viewDidLoad is meant to run **after** the view hierarchy has loaded. – Duncan C Feb 28 '23 at 00:55