Why does the superview of a UITableViewController turns nil after unwindSegue ?

Here is the set up.

  • I have a UITableViewController (controller 1), to which I get from a controller (0)
  • As I need to add a searchView atop the tableView, I addSubview to the superview.
  • This is done in viewWillAppear
        self.view.superview?.addSubview(searchView) // AboveTableView
        searchView.isHidden = true 
        print("willAppear", self.view.superview, self.tableView.superview)

It works perfectly well, I get:

willAppear Optional(<UIViewControllerWrapperView: 0x103d2eef0; frame = (0 0; 393 852); autoresize = W+H; layer = <CALayer: 

From this VC, I segue to another VC (2) with a show segue and comes back with an unwindSegue to return to (1).

Problem is that no, superviews are nil.

    @IBAction func unwindToTableViewController(_ sender: UIStoryboardSegue) {
        
        print("unwind", self.view.superview, self.tableView.superview)
    }

gives

unwind nil nil

If I step back from this controller (1) to the controller (0) from which I segued and segue again to the TableViewController (1), everything works as expected.

In addition, if I go from 1 -> 2 by instantiating (2), everything works OK when I unwind to (1).

I know a solution is to refactor code replacing UITableViewController with a UIViewController and embed a TableView inside. But I would like to understand why my present design does not work.

Accepted Reply

But this should be considered accessing a private view hierarchy (the containment for your view controller) which apps shouldn’t do. Note the superview is a UIViewControllerWrapperView which is an undocumented class internal to UIKit. If it’s not a view you create in your app, then it’s not safe to go add subviews to it or expect any particular behavior from it.

Replies

Replacing show segue (from 1 -> 2) by a showDetail segue apparently solves the problem.

But this should be considered accessing a private view hierarchy (the containment for your view controller) which apps shouldn’t do. Note the superview is a UIViewControllerWrapperView which is an undocumented class internal to UIKit. If it’s not a view you create in your app, then it’s not safe to go add subviews to it or expect any particular behavior from it.

Thanks. I noticed it was a UIViewControllerWrapperView, but wrongly thought it was an accessible property.

Conclusion is that I'll have to refactor code. And that UITableViewController is a bit rigid controller.