Search code examples
jsonswiftuitabbarcontrollerxib

Share JSON Data in TabBarController to view controllers


I am using a tabbarcontroller to show 3 xib's. I would like to decode JSON data in the UITabBarController subclass, and then share the data with the view controllers (as I understand that is the preferred way to do this). I had already successfully accomplished this individually in each view controller, where the same JSON data was getting decoded separately 3 times, but I am now trying to make the process more efficient by only dealing with JSON once.

I am currently getting the following error

"Thread 1: EXC_BAD_ACCESS (code=2, address=0x7ffee7ab7d98)".

Below is the code I am currently using. I'm mostly only including the code for the first view controller, but it is the same for the others

Here is one of the view controllers. Any help would be appreciated, thank you!

class FirstCollectionViewController: UIViewController {

   var tbvc = CustomTabBar()
   var statisticsData = [Model]()

   let firstCellIdentifier = "FirstCellIdentifier"

   @IBOutlet weak var FirstCollectionView: UICollectionView!

   override func viewDidLoad() {
       super.viewDidLoad()

       FirstCollectionView.delegate = self
       FirstCollectionView.dataSource = self

       FirstCollectionView.register(UINib(nibName: "FirstCollectionViewCell", bundle: nil),forCellWithReuseIdentifier: firstCellIdentifier)
   }
}

Here is the subclasses UITabBarController

import UIKit

class CustomTabBar: UITabBarController {

let website = "https:......."

var statisticsData = [Model]()

override func viewDidLoad() {
    super.viewDidLoad()

    let firstTab = FirstCollectionViewController(nibName: "FirstCollectionViewController", bundle: nil)
    let secondTab = SecondCollectionViewController(nibName: "SecondCollectionViewController", bundle: nil)
    let thirdTab = ThirdCollectionViewController(nibName: "ThirdCollectionViewController", bundle: nil)

      viewControllers = [firstTab, secondTab, thirdTab]

    downloadJSON(website: website) {
           firstTab.statisticsData = self.statisticsData
           secondTab.statisticsData = self.statisticsData
           thirdTab.statisticsData = self.statisticsData

           firstTab.FirstCollectionView.reloadData()
           secondTab.SecondCollectionView.reloadData()
           thirdTab.ThirdCollectionView.reloadData()
    }

}

func downloadJSON(website:String, completed:@escaping ()->()){

        guard let qurl = URL(string: website) else { return }

        URLSession.shared.dataTask(with: qurl) { (data, response, error) in
            if error == nil {
                do{

                    self.statisticsData = try JSONDecoder().decode([Model].self, from: data!)

                    DispatchQueue.main.async{
                        completed()
                    }
                } catch {
                    print("JSON Error")
                }}
            }.resume()
   }
}

Solution

  • Once the data is loaded, you should assign the data to the viewControllers that are added in the tabBarController's Child list as below,

    downloadJSON(website: website) {
          firstTab.statisticsData = self.statisticsData
          secondTab.statisticsData = self.statisticsData
          thirdTab.statisticsData = self.statisticsData
    
          firstTab.FirstCollectionView.reloadData()
          secondTab.SecondCollectionView.reloadData()
          thirdTab.ThirdCollectionView.reloadData()
    }
    

    You can also remove the below lines from viewDidLoad of FirstCollectionViewController, SecondCollectionViewController and ThirdCollectionViewController

    tbvc = tabBarController as! CustomTabBar
    statisticsData = tbvc.statisticsData