TJMac
TJMac

Reputation: 159

self.tabBarController.selectedIndex not calling viewDidAppear

I've been looking at and trying all the solutions others have posted to this problem, but I'm still not getting it.

My use case is very simple. I have a viewController with a button, when that button is pressed I want to navigate to another tab and reload the data including an api call.

When using the button, I navigate to the tab fine, but viewDidAppear is not being called.

If on another tab, and navigate using the tab bar, viewDidAppear works fine. Also viewWillAppear is working, but I have to add a manual delay to the functions I want to call so it's not ideal.

So what do I need to do to navigate using self.tabBarController.selectedIndex = 0 and get the functionality of viewDidAppear?

Update: The viewWillAppear method I added gets called but I have to add a delay to my functions in order for them to work, and it's a bit clunky, not ideal. Not sure why viewDidAppear will not work :(

Here is a screenshot of the structure: enter image description here

I appreciate any help on this one!

The "current" ViewController is my tab index 2:

import UIKit

class PostPreviewVC: UIViewController {

//Here I create a post object and post it to the timeline with the below button

    @IBAction func postButtonPressed(_ sender: Any) {

    //create the post via Firebase api

    self.tabBarController?.selectedIndex = 0

    }
}

In my destination viewController:

import UIKit
import Firebase
import SDWebImage
import AVFoundation

class HomeVC: UIViewController {

// MARK: - PROPERTIES

var posts = [Post]()
let refreshControl = UIRefreshControl()
//more properties...


@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    setupUI()
    configureTableView()
    reloadTimeline()

    UserFirebase.timeline { (posts) in
        self.posts = posts
        self.tableView.reloadData()
    }
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    print("viewDidAppear")

    _ = self.view
    setupUI()
    configureTableView()
    reloadTimeline()

    UserFirebase.timeline { (posts) in
        self.posts = posts
        self.tableView.reloadData()
    }
}

override func viewWillAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    print("viewWillAppear")

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        self.reloadTimeline()
        self.configureTableView()
    }
}

//All the tableview code below here...
}

Added a custom class for my tab bar controller:

import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    print("viewDidAppear in tabBar custom Class called")
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    print("viewWillAppear in tabBar custom Class called")
}
}

Upvotes: 2

Views: 1769

Answers (2)

Rahul Umap
Rahul Umap

Reputation: 2859

For UITabBarController viewDidLoad only gets called once. and your viewWillAppear and viewDidAppear get called multiple times. you can either check if your viewWillAppear gets called or not. because your view will appear gets called before your viewDidAppear it's just like going through the reverse engineering process.

You can also add viewDidAppear method into your UITabBarController custom class. and call its superclass method into it in that way I think it will solve your problem.

Note: In the case of UITabbarController, Always do your UI update task and API calling a task in either viewWillAppear or viewDidAppear

Upvotes: 2

Sohel L.
Sohel L.

Reputation: 9540

When you are using UITabBarController, the method viewDidLoad will called only once when any UIViewController is loaded in memory. After that, when you are navigating the same UIViewController, then it will load from memory.

In order to overcome this problem, you must divide your code in viewDidLoad & viewDidAppear. So, in viewDidLoad, you only put that code which you want to intialize once throughout the app such as adding UIView's or other things, while in viewDidAppear / viewWillAppear, you can make API calls or some functions which fetches dynamic data.

Finally, when you are calling self.tabBarController.selectedIndex = 0, it will call viewDidLoad only once and viewDidAppear / viewWillAppear every time when you are navigating that UIViewController.

Hope this helps to understand like how UITabBarController works.

Upvotes: 4

Related Questions