0
votes

My scenario, I am having Tabbar with three viewcontroller. Here, tabbar first viewcontroller I am showing tableview. If I click the tableview cell it will show one popup present model viewcontroller. In this present popup viewcontroller I am maintaining two bar button cancel and done. If I click done It will dismiss and show tabbar main view controller. While dismiss time I need to pass some values with button flag from present popup view controller to tabbar main viewcontroller.

Here, below my dismiss popup pass viewcontroller code (VC 2)

@IBAction func apply_click(_ sender: Any) {
        print("Dimiss Filter")
        dismiss(animated: true, completion: {

            if let navView = self.tabBar?.viewControllers?[0] as? UINavigationController {
                if let secondTab = navView.viewControllers[0] as? HomeViewController {
                    secondTab.selectedIndexFromFirstTab = self.selectedIndex
                    //secondTab.item = self.item
                    secondTab.tfData = "YES"
                }
            }
            self.tabBar?.selectedIndex = 0
        })
    }

Here, Tabbar main view controller code (receiving values) (VC 1)

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

        print("SELECTED INDEX:\(selectedIndexFromFirstTab)")
        print("RESPONSE:\(tfData)")
    }

I am not receiving values, how to solve this issue.

3

3 Answers

2
votes

You can achieve it multiple ways. Using blocks/closures, protocols or if you are using RxSwift than using controlled property or using controlled events. Because I can't demonstrate everything here am gonna write protocol

Using Protocol

Step 1:

Declare a protocol in your modal view controller

@objc protocol ModalViewControllerProtocol {
    func dismiss(with data: String)
}

Step 2:

ViewController that presents this ModalViewController make it to confirm the protocol

extension HomeViewController: ModalViewControllerProtocol {
    func dismiss(with data: String) {
        //use the data here
        self.presentedViewController?.dismiss(animated: true, completion: nil)
    }
}

Step 3:

Declare a variable to hold delegate reference in ModalViewController

weak var delegate: ModalViewControllerProtocol? = nil

Step 4:

In your ViewCOntroller that presents the modalViewController pass self as a delegate to ModalViewController before presenting

    let modalVC = //...
    modalVC.delegate = self
    self.present(modalVC, animated: true, completion: nil)

Finally in IBAction of ModalViewController simply call

@IBAction func apply_click(_ sender: Any) {
    self.delegate?.dismiss(with: "your_data_here")
}

Using Block/Closure

Step 1:

In your modal ViewController declare a property that accepts a block/closure

var completionBlock: (((String) -> ()))? = nil

Step 2:

In your ViewController that presents this ModalViewController, pass a block before presenting it

    let modalVC = //...
    modalVC.completionBlock = {(data) in
        debugPrint(data)
        self.presentedViewController?.dismiss(animated: true, completion: nil)
    }
    self.present(modalVC, animated: true, completion: nil)

Step 3:

Finally in your ModalViewController IBAction simply execute the block passed

    if let block = completionBlock {
        block("your data here")
    }

Hope it helps

2
votes

From my previous answer you need to make few changes to existing code if you want to pass values from your child view to main tab bar controller.

For that first of all you need to declare a method into your main TabBarViewController

func tabPressedWithIndex(index: Int, valueToPass: String) {
    print("selected Index: \(index)")
    print("Value from user: \(valueToPass)")
}

Now you need to pass that tab bar controller to your detail view with didSelectRowAt method and it will look like:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let vc = self.storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
    vc.selectedIndex = indexPath.row
    vc.tabBar = self.tabBarController as? TabBarViewController  // Here you need to assign tab bar controller.
    self.present(vc, animated: true, completion: nil)
}

Now next thing is when you click on dismiss button from detail view controller you need to add one line below self.tabBar?.selectedIndex = 1:

self.tabBar?.tabPressedWithIndex(index: 1, valueToPass: self.userTF.text!)

Now this will pass the values to main tab bar controller and method tabPressedWithIndex will call and print your data in your main tab.

Check out demo project for more info.

1
votes

This is the solution

self.dismiss(animated: true) {
            if let tabController = self.presentingViewController as? UITabBarController {
                if let navController = tabController.selectedViewController as? UINavigationController {
                    if let secondTab = navController.viewControllers.first as? HomeViewController {
                        secondTab.tfData = "YES"
                    }
                } else {
                    if let secondTab = tabController.selectedViewController as? HomeViewController {
                        secondTab.tfData = "YES"
                    }
                }
            }
        }