'initialOpenedSections' Must be set before the tableview has started loading data - uitableview

I have tableview which has multiple sections in my viewcontroller.
And I'd like to open all sections when viewcontroller appeared.
When I navigate to the viewcontroller at first, It works well.
But when I navigate to another viewcontroller and navigate back to this viewcontroller, I've got this error.
'initialOpenedSections' Must be set before the tableview has started loading data.
I've set tableview.initialopensections in viewwillappear().
Please give me suggesstion if you have experienced.

Related

TabBarController's second tab doesn't get instantiated -> IBOutlets are nil

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.
This is how it's supposed to work. Each Tab is created only when it has to be displayed. This the same idea for TableViews and CollectionViews.
The easy one to fix this for you is to override the viewWillAppear (or viewDidAppear) method of your HistoryViewController and refresh the UI from there.
This way, you never assume that the History tab exists in the Summary tab, History refreshes its UI by itself.
Hope this helps.

How can I keep UITableView from reloading on viewDidLoad?

My title probably makes no sense, but I'll do my absolute best to explain it. So, basically, I have a UITableView that's getting data from Firebase. It has a listener, and any time values are changed on that tree, it updates the tableview. The thing is, I put this in viewDidLoad. (which seemed to make the most sense). Say, if the user goes over to the settings screen (a separate VC), and goes back, it reloads the tableview all over again. A couple users are complaining that it takes long to load the tableview when they come back to the main VC, and I was curious if I could keep the data there on THAT vc, so it's permanent until my listener detects a change in the database. Not sure if that makes any sense - but basically the only time I want the tableview to load data is the initial load, AND when data is changed on my backend. Not every time viewDidLoad gets called.
TL;DR:
How do I make it so tableview loads data once, and the data stays even when switching view controllers
viewDidLoad is only called once during the lifecycle of a viewController. You are using a segue to return to your tableViewController from your settings viewController. A segue always instantiates a new destinationViewController. The only exception is the special unwind segue which returns to a previously instantiated viewController.
So, use an unwind segue to return to your tableViewController and your data will still be there and viewDidLoad will not be called.

ViewDidLoad wont fire after pushed to new viewcontroller

So I am trying to get from one viewcontroller to another using the push segue (selected in the storyboard). When I arrive at the second viewcontroller, the viewDidLoad is not firing! Is that a bug or am I doing everything wrong?
It really hard to give suggestion to this kind of question,
Double check below things once.
Is Storyboard View-controller has the Class as the SecondViewController.h
Is the 'View' connected to the outlet as the Seccndviewcontrooler's View.
Performing segue are you sure pushing the SecondViewcontroller only.
Clean build the proj once.
just run the app - Place a NSLog Statment in right after the [super viewDidLoad] and see is that printing logs in console.
try keeping a breakpoint or NSLog at viewWillAppear/viewdidAppear.
What do you mean by pushed to new view? ViewControllers can be pushed not View. ViewDidLoad will be fired only when a ViewController is loaded into the memory. It can also be fired if the VC was unloaded by iOS runtime and is being loaded again.
But thumb rule is that it will fire only when the VC is being loaded not afterwards. Please elaborate your question further if I am interpreting you incorrectly.

How to organize properly the transition back in UITableView

In my app I load data from URL, parsing it, and put in TableView. When user push on some row - initializing method in which pass element's ID and again load data from URL, parsing and reloading TableView. This continues until user saw last element, when he push on it - opens new ViewController (DetailViewController for example). It will be good if user can go back and see in reverse it all. With DetailView all clear - just organized data back with segue, and reload scene.
But the my question is - How to make that when user push Back button on Tableview, TableView reloading in right reverse order?
In this case navigationControl is your friend. Build different views for any click, then instantiate and call the pushViewController with navigationControl. The navigationControl will handle the back button it self.

ViewController loses its properties when I go back

I have two ViewControllers. The first has UITableview that I push data from to the second ViewController. Whenever I go back, the first ViewController loses its properties - Its navigationbar background disappears and for example the sidebar menu does not work either. Is there any way I could reload it while pushing the back button?
Thank you
Sounds like you are probably doing your setup in viewWillAppear instead of viewWillLoad. This means that when the view will appear on return, the setup is happening again and perhaps leaving you in an unexpected state. Put breakpoints in your view controller delegate methods and see what order things are being called in and why.

Resources