UITableView returning nil when reloadData method is called upon it

Project Information:


I have three views: 'Main, AddTask, and TaskTable' and three view controllers: 'MainVC, AddTaskVC, TaskTableVC'. My 'Main' view has an embedded 'UITableView' which is 'TaskTable'. My 'Main' view also has a button that presents a modal view which is 'AddTask'. My 'AddTask' view has a button that dismisses itself. My 'TaskTableVC' has an object named 'taskTable' which is the 'UITableView'



Goal:


I have been trying to call

reloadData
on
taskTable
when the modal view
AddTask
is dismissed. However, no matter how I tackle this I cannot call
reloadData
on the
taskTable
because it always seems to be nil after
AddTask
appears for the first time.



Problem Research:


The first thing I did was directly call

reloadData()
on my
taskTable
object using
completion
when the
AddTask
was dismissed :


self.dismiss(animated: true, completion: { 
     TaskTableVC().taskTable.refreshData() 
})


but I quickly learned that I cannot call it directly because the

TaskTable
view was not loaded and I was creating an instance.

Next, I put print statements on my

viewDidLoad
for my three views (see Project Information). On startup, the first thing that loads is my
TaskTable
and then my
Main
. When I click a button on my
Main
my
AddTask
loads. So far so good... However, when I dismiss my
AddTask
, nothing loads. I thought my
TaskTable
and
Main
would get loaded but that was not the case. So I tried calling a function
refreshData()
that was part of
MainVC
on
completion
of
dismiss
in
AddTaskVC
The function would load the
TaskTable
view using
loadViewIfNeeded
:


func refreshData() { 
     TaskTableVC().loadViewIfNeeded() 
}


Then in my

TaskTableVC
under my
viewDidLoad
I have:


override func viewDidLoad() { 
     super.viewDidLoad() 
     print("table view loaded") 
     self.taskTable.reloadData() 
}


Yet the error I continue to get is:

Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value


I believe this is because I called

TaskTableVC.loadViewIfNeeded()
via an instance? Whatever the case may be, I cannot get this to work for the life of me.


TL;DR I need to call

reloadData
on an embedded
UITableView
when I call dismiss on a modal view.
//MainVC: 
class MainVC: UIViewController { 
     override func viewDidLoad() { 
          super.viewDidLoad() 
          // Do any additional setup after loading the view. 
          print("main view loaded") 
     }  
     func refreshData() { 
          TaskTableVC().loadViewIfNeeded() 
     } 
}
//AddTaskVC
class AddTaskVC: UIViewController { 
     override func viewDidLoad() { 
          super.viewDidLoad() 
          // Do any additional setup after loading the view. 
          print("AddTask view loaded") 
     } 
     //... 
     @IBAction func addTask(_ sender: Any) { 
          //... 
          self.dismiss(animated: true, completion: { 
               MainVC().refreshData() }) 
     } 
}
//TaskTableVC
class TaskTableVC : UITableViewController {  
     @IBOutlet var taskTable: UITableView!  
     override func viewDidLoad() { 
          super.viewDidLoad() print("table view loaded") 
          self.taskTable.reloadData() //error here 
     } 
     //... 
}

Replies

Your tableView is in Main View controller, right ?


So, why do you create a new TableViewController ?


You should either:


- create an IBOutlet in MainVC, to connect to the tableView from IB: move

@IBOutlet var taskTable: UITableView!

here

- remove the tableViewController from IB and from code


OR, if you need to keep a TableViewController:

- segue to it from MainVC, either with a showTableButton or just when you tap on the MainVC

- in that cae, no need to define an IBOutlet inside TaskTableVC ; it is buil-in when creating UITableViewController

To confirm, yes my TaskTable view is in a container that is part of my Main view. I have a segue that embeds the TaskTable view to my container in my Main view. I am not sure how I would keep an embedded view while deleting the TaskTableVC. Thanks.

Did you try to do what I suggested:


- create an IBOutlet in MainVC, to connect to the tableView from IB: move

@IBOutlet var taskTable: UITableView!

- remove the tableViewController from IB and from code


The tableView will remain in MainVC, with its IBOutlet to reference it.

I actually found another solution involving delegates and protocols that worked. Thank you though!

Thanks for feedback.


I would have been interested to know if the proposed solution worked for you.


nevertheless, don't forget to mark the thread as closed.