iosswiftpass-data

how to update label of other viewController in swift


I'm trying to set UIbutton's text in firstVC as selectedCity variable when it selected in tableViewCell in SecondVC . I cannot use segue or tabBarController. Updated photo of ui

FirstVC

import UIKit

class homeView: UIViewController{

    @IBOutlet weak var selectRegion: UIButton!
}

SecondVC

import UIKit

class selectCityPage: UIViewController, UITableViewDelegate, UITableViewDataSource {
   
    @IBOutlet weak var tableView: UITableView!
    var selectedCity: String!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = self
        tableView.delegate = self

    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
      
        if indexPath.row == 0{
            selectedCity = "Almaty"
            
            
            
        }
        if indexPath.row == 1{
            selectedCity = "Усть-Каменогорск"
            
        }
        dismiss(animated: true, completion: nil)
       // when this view controller is dismissed, uibutton's text in next viewcontroller should equal to selectedCity
        
    }
}

Solution

  • You can use delegation. These are the required steps:

    1. Create a delegate protocol that defines the messages sent to the delegate.
    2. Create a delegate property in the delegating class to keep track of the delegate.
    3. Adopt and implement the delegate protocol in the delegate class.
    4. Call the delegate from the delegating object.

    SecondVC

    import UIKit
    
    //1. Create a delegate protocol
    protocol CitySelectionDelegate {
      func pickCity(with selectedCity:String)
    }
    
    class SelectCityPage: UIViewController, UITableViewDelegate, UITableViewDataSource {
       
        @IBOutlet weak var tableView: UITableView!
        var selectedCity: String!
    
        //2. Create a delegate property in the delegating class
        var delegate:CitySelectionDelegate?
    
    
        //other stuff 
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
    
        if indexPath.row == 0{
           selectedCity = "Almaty"
        }
        if indexPath.row == 1{
           selectedCity = "Усть-Каменогорск"
        }
    
        4. Call the delegate from the delegating object.
        delegate?.pickCity(with: selectedCity) //call your delegate method 
        
        //dismiss(animated: true, completion: nil)    when you dismiss is up to you    
        }
    }
    

    HomeViewController UPDATE: Since you have another VC embedded inside a UINavigationController, both the Home and Select Region Page MUST conform to the delegate and you have to set the delegate inside prepareForSegue method.

    // 3. Adopt and implement the delegate protocol
    class HomeViewController: UIViewController, CitySelectionDelegate{
    
    @IBOutlet weak var selectRegion: UIButton!
    
       func pickCity(with selectedCity: String) {
          self.selectRegion.text = selectedCity
       }
    
     /*please pay attention. In this case you must reference the   
     navigation controller first and the your can get the right 
     instance of the delegate variable inside your firstVC (I called   
     firstVC but in your case is Select Region Page*/
    
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
             // you MUST set the right identifier 
            if segue.identifier == "showFirst" {
                if let navController = segue.destination as? UINavigationController {
                    if let firstVC = navController.topViewController as? FirstViewController{
                        firstVC.delegate = self
                    }
                }
            }
        }
    }
    

    since you have another VC (embedded in a navigation controller), also this one must conform to the delegate like so:

    class FirstViewController: UIViewController, CitySelectionDelegate {
    
    var delegate: CitySelectionDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func pickCity(with selectedCity: String){
        // here you simply call the delegate method again and you dismiss the navigation controller 
        self.delegate?.pickCity(with: selectedCity)
        self.navigationController?.dismiss(animated: true, completion: nil)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showSecond" {
            if let controller = segue.destination as? SelectCityPage {
                controller.delegate = self
            }
        }
    }