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.
Related
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 want to use a pull-to-refresh UI action to trigger a segue to a modal view. The action works fine, triggering the modal segue as expected. But when I dismiss the modal, the refresh control view is still visible.
I am correctly calling refreshControl.endRefreshing() before the segue, but the problem seems to be that the UI doesn't have time to complete the animation that dismisses the refresh control view before the segue is trigger, so it gets suck half way.
If I place a small delay (0.4s) before triggering the segue this kind of helps, as it allows the animation to complete, but it feels like a hack. Also, if the user pulls down really slowly on the tableview, and releases the pull-down later than after 0.4 seconds, the same problem occurs.
How can I ensure that the refresh control will not be visible when I dismiss the modal view? Ideas I have (but which I can't find a way to implement) include:
1) ensuring the animation that dismisses the refresh control has time to complete before the segue is triggered.
2) dismiss the refresh control view on the parent view when I dismiss the modal.
I can't get either of the above to work though.
With 1) a delay works (sometimes), but feels like a hack.
With 2) tableView.reloadData() only reloads the tableview, not the whole view, so the refresh control remains.
Any help would be greatly appreciated.
Here is the code that implements the refresh control.
lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToAddCard(_:)), for: .valueChanged)
return refreshControl
}()
And here is the code that gets triggered by the refresh control
#objc func pullToAddCard(_ refreshControl: UIRefreshControl) {
refreshControl.endRefreshing()
delay(0.4, closure: {
self.performSegue(withIdentifier: "segueFromPlaylistDetailToNewCard", sender: self)
})
}
And here is a screenshot of what the parent view looks like when I nav back to it (by dismissing the modal view.) The 'stuck' refresh control view is visible at the top.
Just add
refreshControl?.endRefreshing()
to your viewWillAppear method
I just tried the following using the storyboard below, and it works fineā¦
class TableViewController: UITableViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
refreshControl?.endRefreshing()
}
#IBAction func unwind(sender: UIStoryboardSegue) {
}
}
Ok, I found a solution. #Ashley Mills' answer gave me an idea. In viewWillAppear I call refreshControl.beginRefreshing(), and then immediately call refreshControl.endRefreshing(), and that works!
For some reason, simply calling refreshControl.endRefreshing() wasn't enough.
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
}
Here's what I'm trying to do:
I have 2 views, Settings and Main Screen.
I've coded a segue to occur when a button in Settings is pressed, taking the view to the Main Screen. The identifier is "reset".
I'm trying to have the Main Screen perform a series of actions if this segue is triggered, but I can't find the function or way to do this.
Any help on how to implement this? I'd like it to trigger when the segue occurs.
You can pass arguments to the main screen in the prepareForSegue function in the settings page. Then in your main screen you can put in checks in your viewWillAppear function to handle them as you see fit.
Example:
In Settings:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "reset") {
// pass data to next view
let viewController:ViewController = segue!.destinationViewController as MainViewController
viewController.settings = settings // where settings is what you want to pass
}
}
In Main Screen:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if self.settings { // Do something }
}
If you're wanting something to happen when the segued view controller is triggered you can do it in a couple of places.
If you want the event to happen at the time the segue is fired, perform your code inside of prepareForSegue. There you can check the UIStoryboardSegue object's identifier field for "reset" and if true, call your logic.
If you want it to happen when the destination view controller loads or appears, do it inside of its viewDidLoad or viewDidAppear methods. In your case those methods would exist on the "Main Screen" view controller class.
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 :)