I have a UITableView and the cells display data that is fetched from my backend. I can navigate to different view controllers from the view controller that contains my tableview. When I segue back to my view controller with the tableview, I want to update the table with an updated fetch request.
As of now I have:
override func viewDidLoad() {
self.fetchData()
self.dataTable.reloadData()
}
override func viewWillAppear(animated: Bool)
{
self.fetchData()
self.dataTable.reloadData()
}
This just causes the tableview to be redundant and display the same data (obviously). What would be the correct way to update the table without displaying the same information? Should I clear the array from the prior fetch request before each fetch request?
You have to remember that viewDidLoad() is only called once during navigation segues. So, after it's loaded, the only time you'll know that the view has popped up again is in the viewWillAppear().
Have you tried:
override func viewWillAppear(animated: Bool)
{
self.clearData()
//Once you've reset all your variables, populate them again.
self.fetchData()
self.audioData.reloadData()
self.dataTable.reloadData()
}
If I'm wrong, and your viewDidLoad() method is being called every time the view appears, then your code should work. You can always put print statements in each function to see what's being called, and what isn't. Let me know if this helps :)
Related
I have set up a button in my iOS App that performs segue from 1st View Controller to 2nd View Controller. But, there is a delay of about 3-5 seconds on moving from 1st View Controller to 2nd View Controller. Is there any way by which this delay can be avoided and the user can easily go to the 2nd View Controller on the click of the button without any delay? Would appreciate it if anyone could provide any suggestions on how can I eliminate this issue? Thanks a lot for the help:)
#IBAction func startButton(_ sender: Any) {
performSegue(withIdentifier: "1to2segue", sender: self)
}
The 2nd View Controller displays live stats extracted from an external source. Thus, it takes time to load up. How can I make this process faster?
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
In your second view controller, do NOT call your loadData() func in viewDidLoad().
You want to do as little as needed to get the view on the screen. Show a spinner or some other "Loading Data..." activity view.
Then, perhaps in viewDidAppear(), call your loadData() func. But make sure whatever you're doing in loadData() is being done in an async process.
I have a tableViewController that holds a list of activities. Theres a button that takes you to a new view controller, which allows you to create a new activity, that then gets inserted into the database when the save button is pressed, which also dismisses the view controller to take you back to the list of activities. I want the activities to refresh so that the new activity they just inserted will be added to the table. I have tried
nextViewController = ActivitiesViewController()
dismissVC(){
nextViewController.viewDidLoad() }
It currently takes you back to the correct table view, but the rows do not update. It isn't until the phone is restarted that the values update.
Anyone have any ideas on how to fix this?
Thanks
You probably want to override the method viewWillAppear(_ animated: Bool) in your ActivitiesViewController and call a function to update the data (just as you do in viewDidLoad).
class ActivitiesViewController: UITableViewController { // UITableViewController or whatever you're using
// your stuffs
// ...
// ...
override func viewDidLoad() {
super.viewDidLoad()
// load datas
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// load datas
tableView.reloadData()
}
}
To explain a bit further why you should do this; in your code snippet, you're creating a new instance of ActivitiesViewController that is not the one that is displayed on the screen. Even if you update it, it's not linked to the one that is displayed.
I am trying to find the solution for how to automatically reload all the data in view controller but i can't find any. Right now i am using push to refresh to reload the button/title/data in view controller viewDidload() but i want to have it automalliy reload everything every time i come back to this viewcontroller. For example when app lunched, it load view controller A then i clicked on the button to go View controller B but i want to controller A to refresh everything after back from B so how can i do that?
Thanks
For this, there is a method viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
reloadData()
}
func reloadData() {
//All you need to update
}
I have a tableView into a viewController on tab Bar. When I click into tabBar item the tableView isn't refreshing. But I have the viewWillAppear function:
override func viewWillAppear(animated: Bool) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
I'm trying call this function with tab bar delegate, but not works:
func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
}
Why not reload?
Thanks!
You do not need to involve the tab bar controller in this. To do so would be overkill. You'll create confusing code that somebody will want to rip out later. Updating the table view in viewWillAppear(_:) is almost always the best approach.
If everything is set up properly, your view controller's viewWillAppear(_:) method will get called each time the user selects that tab and your view becomes visible. So if it's not getting called, you have a problem somewhere in the design of your tab bar and its view controllers.
Create a new project and select the Tabbed Application template. Open the SecondViewController file and add a viewWillAppear(_:) method. Add a breakpoint there. You'll see it's called every time you switch to the second tab.
Some other thoughts...
You'll notice in the viewWillAppear(_:) documentation that it says you must always call super. You're not. You should. But this is unrelated to your problem.
Also, there's no need to switch to the main queue. viewWillAppear(_:) will always be called on the main queue.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
Answer for swift 5.0
Reload UITableView in main thread and then check. I hope this will work for you.
override func viewWillAppear(_ animated: Bool) {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
You can find the answer here:
open viewcontroller from tab like in instagram camera page on IOS
Basically, you need to create a controller which inherits from UITabBarController and set it in the Storyboard to the custom class of your tabBarView.
Then set Tags to each Tab via the Storyboard.
Afterwards you can use the delegate method to call an action if a specific tab was clicked.
The delegate method should look like this:
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
switch item.tag{
case 1: //code here
break
default: break
}
}
I got my table view on top of a map view. I want to show to user that the tableView is scrollable. Here is my previos thread: Swift - How to attach bar to the top of table view?
I tried using
self.tableView.flashScrollIndicators()
in my ViewDidLoad() method but this doesn't change anything, the table view looks exactly the same as before. I read suggestion that it might be caused by reloading tableView and filling it with data, whilst created tableView is empty. Nonetheless I tried pasting the flashScrollIndicators() method in other project where table is created with cells immediately - again no significant difference.
Am I doing something wrong or using the method in wrong place?
If anyone is still fighting with this problem here is my working solution - works on iOS 11. In my case flashScrollIndicators() did not work on first invocation of viewDidAppear(animated:). Invoking flashScrollIndicators() with a delay will do the trick.
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
DispatchQueue.main.asyncAfter(deadline: (.now() + .milliseconds(500))) {
self.collectionView.flashScrollIndicators()
}
}
You're using the method in the wrong place. In viewDidLoad, the view has just finished loading. It hasn't yet been displayed. A safe alternative would be to move the call into your view controller's viewDidAppear: method to make sure that you don't attempt to flash the scroll indicator until the view is already on screen.
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.tableView.flashScrollIndicators()
}
Swift 4
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.tableView.flashScrollIndicators()
}