Changing Vc Issue in Swift. How to Pass Data Between Views in Tab Bar Controller

Changing VC issue in Swift. How to pass data between views in tab bar controller?

From your Storyboard diagram, it is clear that you have created a segue from each button in your "tab bar" to another view controller. Except for the unwind segue, segues always create a new instance of the view controller they are switching to. So if you use your setup to switch from view controller 1 to view controller 2 and then back to view controller 1, you won't be returning to the view controller you came from but instead you will be creating an entirely new view controller 1.

This is why your memory consumption is excessive. You keep creating view controllers until your app crashes.

I would recommend you return to using a tab bar controller. They were designed to allocate the view controllers once up front and then just switch between them. Also, they have a standard look for a reason, it helps the user of your app know immediately how to interact with them.


To pass data between tabs, you won't use segues because there is no segue happening when you switch tabs. There are many ways you can do this, but they all boil down to having model data stored where all of the tabs can access it. This can be done with CoreData in a larger app. For a simple app, you can do the following:

  1. Create a custom subclass of UITabBarController. Let's call it CustomTabBarController. Have that class create and hold the model data that will be accessed by each of your tabs.

    CustomTabBarController.swift:

    import UIKit

    // This class holds the data for my model.
    class ModelData {
    var name = "Fred"
    var age = 50
    }

    class CustomTabBarController: UITabBarController {

    // Instantiate the one copy of the model data that will be accessed
    // by all of the tabs.
    var model = ModelData()

    override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    }
    }
  2. In your Storyboard, in the Identity Inspector, change the class of UITabBarController to CustomTabBarController.

    Sample Image

  3. In viewWillAppear in each of your tabs, get a reference to the model data and then you can use it.

    FirstViewController.swift:

    import UIKit

    class FirstViewController: UIViewController {

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

    // Get a reference to the model data from the custom tab bar controller.
    let model = (self.tabBarController as! CustomTabBarController).model

    // Show that we can access and update the model data from the first tab.
    // Let's just increase the age each time this tab appears and assign
    // a random name.
    model.age += 1

    let names = ["Larry", "Curly", "Moe"]
    model.name = names[Int(arc4random_uniform(UInt32(names.count)))]
    }

    }

    SecondViewController.swift:

    import UIKit

    class SecondViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var ageLabel: UILabel!

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

    // Get a reference to the model data from the custom tab bar controller.
    let model = (self.tabBarController as! CustomTabBarController).model

    // This tab will simply access the data and display it when the view
    // appears.
    nameLabel.text = model.name
    ageLabel.text = "\(model.age)"
    }
    }

Passing data from a tab bar switch right into another view controller

Your pass data task is going though this process

V12 --(pop)--> V11 --(switch)--> V21 --(push)--> V22

If you choose to pass data, you will need to pass it though all these three transactions and that's lots of coding and it's hard to practice.

Instead of passing data around, a better way to accomplish your goal is to store the data in V12, and then load it from V22. So now all you need to worry about is how to transfer user from V12 to V22.

You only need two lines of code to store and read data from UserDefaults

On your V12, before you are doing the above transactions, first save your data like this

UserDefaults.standard.set("yourStringData", forKey: "data")

Then when you reach VC22, from viewDidLoad, read stored info in this way

UserDefaults.standard.string(forKey: "data")

For your view transaction part, popToViewController is for going from a child view controller to it's parent. So when you switch your tab and get the UINavigationController, the topViewController must be VC21. So to go to VC22 given that you connect them though a storyboard segue, simply call it like this

let navController = self.tabBarController?.viewControllers![1] as! UINavigationController
let VC21 = navController.topViewController!
VC21.performSegue(withIdentifier: "segue", sender: nil)

How to pass data between two view controllers of a TabBarContoller where the first view controller is a TableViewController

The best way to pass data between two viewcontrollers is to get reference of viewcontroller where you want to pass data.

Suppose in ViewController1 user select some tableview cell then in method

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let secondVC = self.tabBarController?.viewControllers?[1] as? ViewController2 {
self.tabBarController?.selectedIndex = 1
secondVC.instanceVariable = "updated value"
}
}

This will take to viewController2 and update the instance variable value.Now in viewWillAppear method you can reload mapview.

passing data between viewControllers under a tabController in swift, event sequence

You are using:

// this is called when the tab's ViewController is selected (*after* the tab item is selected (tapped))
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { ... }

when you want to use:

// this is called *when* the tab item is selected (tapped)
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { ... }

Here is a modification to your example:

import UIKit

class MainViewController: UITabBarController, UITabBarControllerDelegate {

override func viewDidLoad() {
super.viewDidLoad()
delegate = self;
}

override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {

let n = self.selectedIndex

if let tabControllers = viewControllers {

if let _ = tabControllers[n] as? AViewController {
// *current* VC is AViewController
if let vcB = tabControllers[n + 1] as? BViewController {
vcB.Y = "some valuable data from A"
}
}

else if let _ = tabControllers[n] as? BViewController {
// *current* VC is BViewController
if let vcA = tabControllers[n - 1] as? AViewController {
vcA.Y = "some valuable data from B"
}
}

}

}

}

class AViewController: UIViewController {

@IBOutlet weak var YTextField: UITextField!

var Y:String = ""

override func viewDidLoad() {
super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
YTextField.text = Y
}

}

class BViewController: UIViewController {

@IBOutlet weak var YTextField: UITextField!

var Y:String = ""

override func viewDidLoad() {
super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
YTextField.text = Y
}

}

You'll want to do some additional handling / checking to make sure you're getting to the desired tab. You may want to set a variable inside MainViewController on didSelect item and then set the variable inside the "target" view controller on didSelect viewController.

How to Pass data between tabBarControllers

I would subclass the UITabBarController and make it a delegate for the two UITableViewControllers.

CustomTabBarController

protocol CustomTabBarDelegate {
var places:Array { get set }
}

class CustomTabBarController: UITabBarController, CustomTabBarDelegate {
var places = Array()

override func viewDidLoad() {

places = [PlaceData(),PlaceData()]

var table1 = CustomTableViewController()
var table2 = CustomTableViewController()

table1.delegate = self
table2.delegate = self

var navController1 = UINavigationController(rootViewController: table1)
var navController2 = UINavigationController(rootViewController: table2)

self.viewControllers = [navController1, navController2]

}
}

Then your TableViewControllers simply access the delegates array like so.

CustomTableViewController

class CustomTableViewController: UITableViewController {
var delegate:CustomTabBarDelegate!

override func viewDidAppear() {
self.tableView.reloadData()
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return delegate.places.count
}

}

Any changes to the array will be visible in each table after you .reloadData() - I have set the CustomTableViewController in my example to reload data every time the view appears, so when you change tabs they should refresh to show the latest changes.


It's worth mentioning that in time it would probably be cleaner to have a separate class that manages your data instead of holding the array in the TabBarController.

Data transfer between child tabs in a Tab bar controller

Try this:

I have created a UITabBarController with 2 child controllers Tab1ViewController and Tab2ViewController.

Screenshot of storyboard:

Sample Image

Code:

class Tab1ViewController: UIViewController
{
@IBOutlet weak var testTextField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
}
}

class Tab2ViewController: UIViewController
{
@IBOutlet weak var testLabel: UILabel!
override func viewDidLoad()
{
super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
let tab1Controller = self.tabBarController?.viewControllers?.first as! Tab1ViewController
self.testLabel.text = tab1Controller.testTextField.text
}
}

Similarly you can create 4 tabs and other textfields.

For more refer to : How do I pass data from a tab bar controller to one of its tabs?



Related Topics



Leave a reply



Submit