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
}
}
Related
I'm currently building a homework tracking app where you can add courses in a TableView. In one ViewController, I have a list of courses that already exist. I also have a button that allows the user to add new courses. When they click the button, the app triggers a modal segue to a new ViewController where they can fill out a form to add a new course. However, when they finish and click the button that dismisses the current ViewController to go back to the courses list, I can't find a way of updating the courses list with the course that the user just added. I know that if using a segue, you can use the prepare method. However I am calling
dismiss(animated: true, completion: nil)
The method that I want to call in order to reload the table is in the first ViewController. Is there a way to call the load method in the first ViewController before or after the second ViewController has dismissed?
As per your requirement, a simple "delegation" will work.
Step 1: Define a protocol.
protocol ViewController2Delegate: class {
func refresh()
}
Step2: Create a delegation at ViewController2
weak var delegation: ViewController2Delegate?
Step3: As you are using "segue" from a button to create ViewController2 from ViewController1, use prepareForSegue method in ViewController1 and set that ViewController1 is conforming the delegate. ViewController1 will conform the delegate and reload the table.
Step4: In ViewController2, on tap of doneButton, call delegate?.refresh() as per your requirement (before dismissing / after dismissing of viewcontroller2 - use completionBlock of dismiss() method).
you can use viewWillappear function in first view controller to refresh or just using completion handler as next:
1) in the second controller add this variable.
var completion: (() -> Void)?
2) in the first controller before showing the second controller you need to add this code.
let controller = secondController()
controller.completion = {
// here you can refresh your first controller
}
3) to make the refresh here is the last step you need to do in the second controller before you call the dismiss function.
if let completion = completion{
completion()
}
You can call reloadData in viewWillAppear on ViewController1
override func viewWillAppear(_ animated: Bool) {
tableview.reloadData()
}
You could do the loadData or refreshData on viewWillAppear of the FirstViewController, like this:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
refresData()
}
The viewWillAppear of FirstViewController will be called right after you call to dismiss from the SecondViewController.
You can use a delegate for the first controller in you second view controller and call it before you call the dismiss. If you want to to run after the dismiss, then you can call it in the completion of the dismiss function.
I have weird situation and have no clue how to debug it. I load three viewControllers in navigation controller. When Im navigating back from there second and first ViewController doesn't display anything just white screen I added print methods everywhere in lifecycle methods and it seems that it loads views but anyway they not visible. What could be the problem?
Yep It's weird, There maybe some code which do something with your view on such events like:
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// remove some subviews or change constraints.
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// remove some subviews or change constraints.
}
Please send us a code of the view controller which has the problems and code how exactly you show the controller.
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 want to refresh the whole page controller on back press.
I am navigating the viewcontroller using code.
My Code
let GTC = self.storyboard?.instantiateViewController(withIdentifier: "GoToCart")as! GoToCart
self.navigationController?.pushViewController(GTC, animated: true)
Using viewWillAppear to reload your UI. As you use navigationController?.pushViewController, the view will be retained and stored in stack.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Reload the UI
}
viewWillAppear(_:)
viewWillAppear is called the first time the view is displayed as well as when the view is displayed again, so it can be called multiple times during the life of the view controller object. It’s called when the view is about to appear as a result of the user tapping the back button, when the view controller’s tab is selected in a tab bar controller etc. Make sure to call super.viewWillAppear() at some point in the implementation. You can refresh your UI in this method
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Reload the UI
}
A better approach is to use protocol
Create protocol from where you want to pop back(GoToCart)
Create delegate variable in GoToCart
Extend GoToCart protocol in MainViewController
Give reference to GoToCart of MainViewController when
navigate
Define delegate Method in MainViewController
Then you can call delegate method from GoToCart
Example
In GoToCart: Write code below..
protocol GoCartControllerDelegate
{
func childViewControllerResponse(parameter)
}
class GoToCart:UIViewController
{
var delegate: ChildViewControllerDelegate?
....
}
Then in mainViewController implement the protocol function end extend to the protocol
class MainViewController:UIViewController,GoCartControllerDelegate
{
// Define Delegate Method
func childViewControllerResponse(parameter)
{
//...here update what you want to update according to the situation
}
}
2 Important thing
when navigating to the gocart controller code like this
let GTC = self.storyboard?.instantiateViewController(withIdentifier: "GoToCart")as! GoToCart
GTC.delegate = self
self.navigationController?.pushViewController(GTC, animated: true)
and when popping from gocartViewController
code like this
self.navigationController?.popViewController(animated:true)
self.delegate?.childViewControllerResponse(parameter)
I am using a tab bar controller and I wonder if there is a way to check which tab is being clicked?
If the user clicks on the "account" tab and is not logged in I want to redirect to a full screen modal login screen instead of the account VC.
You can do it in your custom UITabBarController or somewhere, and override the 'didSelectItem' function.
import UIKit
class TabbarViewController: UITabBarController {
override func viewDidLoad() {
}
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
print("Selected Index :\(self.selectedIndex)");
}
}
In the scenario you outlined, I would check to see if current user is logged in or not, and if not segue to the appropriate screen of your application.
UITabBarDelegate's didSelectItem
The options that others have provided are fine, but I wanted to let you know of another way. In the viewWillAppear, viewDidAppear, or viewDidLoad functions, you can call what you need to segue to a login ViewController