I'm creating a simple app which has a tab bar controller where the summary is one tab and the history is another. In the summary tab, there is a button to add a new round. Whenever this round gets added it has to go to the history tab as well.
I'm trying to send the data through the tabBarController.
What I'm experiencing is whenever I don't open the history tab before adding a new round my program crashes because my IBOutlets are nil. But whenever I open the tab first and then go back to add a new round it works fine. I also don't have to reopen the tab after every round. It looks like the tab isn't getting instantiated before I open it up the first time.
Gif of failure (Error is that the Chart View
is nil):
http://i.imgur.com/VPa0RmK.gifv
Gif of success: http://i.imgur.com/LqxYBjV.gifv
Is there any way to do this manually?
I'm new to iOS programming so that is what I think the problem is. If there's happening something else that's crashing my code I'd like to know!
You are right. The problem is that the outlets for the second tab do not get set up until you visit that tab.
Solutions:
You can write the data to a property of the second viewController, and then move that data into the outlet in an override of viewWillAppear
.
Another possibility is to check if the outlet is nil
before you write to it. If it is, call loadView
on the second viewController to tell it to set up its outlets, and then you'll be able to write to them. Note, if you call loadView
manually, the method viewDidLoad
will then not run, so if you're doing any additional setup in there, you'll also need to do that from loadView
.
Perhaps even simpler than calling loadView
manually is to trigger the viewDidLoad
of the secondViewController by accessing the view
property. This can be as simple as:
if let svc = self.tabBarController?.viewControllers?[1] as? SecondViewController {
// check if outlet is nil
if svc.myLabel == nil {
// trigger viewDidLoad to set up the outlets
_ = svc.view
}
svc.myLabel = "Success!"
}
That said, directly accessing another viewController's views (i.e. outlets) is poor design and a violation of the MVC (Model-View-Controller) paradigm. You should really put your data in a place that can be accessed by all tabs and then have each viewController update itself in viewWillAppear
when the tab is selected. See this answer: Sharing data in a TabBarController for one way to do this.