Ahmed
Ahmed

Reputation: 61

how to perform segue to a VC with Container

see this image

see this gif

when I choose the city Med , it passed to the TableVC not to the FirstVC (MainVC)

can I do that ? segue to the mainVC with the data passed through the container (TableVC) ?

here what I did so far

MainVC

Empty

TableVC

import UIKit

class passedViewController: UITableViewController {

@IBOutlet weak var passcelltow: UITableViewCell!
@IBOutlet weak var passcell: UITableViewCell!

var passedCity1 = "اختر المدينة الاولى"
var passedCity2 = "اختر المدينة الثانية"
 override func viewDidLoad() {
    super .viewDidLoad()

    passcell.textLabel?.text = passedCity1
    passcelltow.textLabel?.text = passedCity2

}

}

Table 1 with data to pass to the TableVC

import UIKit

class city2ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource{
@IBOutlet weak var tableView: UITableView!

var city2 = ["RUH" , "Med" , "Jed"]

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell()
    print(indexPath.row)

    cell.textLabel?.text = city2[indexPath.row]

    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: "show", sender: city2[indexPath.row])
}


override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    let passing = segue.destination as! passedViewController

    passing.passedCity2 = sender as! String

}




}

Table 2 is the same ..

commend error

0 1 2 Could not cast value of type 'UIViewController' (0x107a10288) to 'table_view_test_pass.passedViewController' (0x105dbfdf8). (lldb)

Upvotes: 1

Views: 841

Answers (3)

Kegham K.
Kegham K.

Reputation: 1614

You can pass data via segues or protocols. Since you are using segues i will show you a complete example and how to do it the right way in Swift 3. Using only two ViewControllers.

  1. Create two UITextFields in the main "ViewController".
  2. Create a new view controller of type UIViewController call it "MainTabelViewController" and add a tableView in it. Select content Dynamic prototypes Style Grouped and create 1 prototype cell and add a UILabel to it for the city name. "Don't forget the put the cell identifier name". I called it "cell".
  3. Add the delegates and data sources to the class and add its functions like in code.
  4. Create a segue from the main view controller to the main table view controller. And create another segue the opposite direction. "Don't forget the put the segue identifier names" I called them "toCity" & "toMain"
  5. Create a "CityTableViewCell" controller of type UITableViewCell and create an IBOutlet of UILabel type where you will save the city name in as a text.

Edit this part in the AppDelegate.swift To delete the city names saved using in the UserDefaults every time the app is launched. So i wont populate the UITextFields randomly every time.

import UIKit


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var userDefaults: UserDefaults!

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        userDefaults = UserDefaults.standard
        userDefaults.removeObject(forKey: "City One")
        userDefaults.removeObject(forKey: "City Two")

        return true
    }

This is the ordinary main ViewController.swift where you have your UITextFields in. I distinguish which UITextField did the user click on using the tags. You need to add also the UITextFieldDelegate protocol to be able to use the the textFieldDidBeginEditing function. And i also save the selected city names using UserDefaults class to call them when user chooses the other city.

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var cityOneLabel: UITextField!
    @IBOutlet var cityTwoLabel: UITextField!

    @IBOutlet var continueButton: UIButton!

    var selectedCityOne = ""
    var selectedCityTwo = ""

    var userDefaults: UserDefaults!

    override func viewDidLoad() {
        super.viewDidLoad()

        cityOneLabel.delegate = self
        cityTwoLabel.delegate = self

        cityOneLabel.tag = 1
        cityTwoLabel.tag = 2


        continueButton.isEnabled = false


    }

    override func viewDidAppear(_ animated: Bool) {

        userDefaults = UserDefaults.standard

        cityOneLabel.text = selectedCityOne
        cityTwoLabel.text = selectedCityTwo

        if selectedCityOne != "" {
            userDefaults.set(selectedCityOne, forKey: "City One")
        } else {
            cityOneLabel.text = userDefaults.string(forKey: "City One")
        }
        if selectedCityTwo != "" {
            userDefaults.set(selectedCityTwo, forKey: "City Two")
        } else {
            cityTwoLabel.text = userDefaults.string(forKey: "City Two")
        }


    if cityOneLabel.text != "" && cityTwoLabel.text != "" {

            continueButton.isEnabled = true
        } else {
            continueButton.isEnabled = false
        }

    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func continueButtonAction(_ sender: UIButton) {

        //Later on continue after selecting the cities
    }



    func textFieldDidBeginEditing(_ textField: UITextField) {

        performSegue(withIdentifier: "toCity", sender: textField.tag)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "toCity" {

            guard let cityVC = segue.destination as? MainTableViewController else {
                return
            }

            cityVC.selectedTextField = sender as! Int
        }
    }

}

In the CityTabelViewCell.swift add the IBOutlet UILabel for the city name.

import UIKit

class CityTableViewCell: UITableViewCell {

    @IBOutlet var cityNameLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

For the MainTabelViewController.swift write this: Here is where i create an array of strings to populate my table view UILabels with.

import UIKit

class MainTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var cityTabelView: UITableView!

    var cityNamesArray = ["Cairo", "Alexandria", "Suez"]

    var selectedTextField = Int()

    var selectedCityName = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        cityTabelView.delegate = self
        cityTabelView.dataSource = self

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

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

     func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CityTableViewCell

        cell.cityNameLabel.text = cityNamesArray[indexPath.row]

        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return cityNamesArray.count
    }

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

        selectedCityName = cityNamesArray[indexPath.row]

        performSegue(withIdentifier: "toMain", sender: self)
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

        var title = ""
        if selectedTextField == 1 {
            title = "City One"
        } else if selectedTextField == 2 {
            title = "City Two"
        }

        return title
    }



    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "toMain" {
            guard let mainVC = segue.destination as? ViewController else {
                return
            }
            if selectedTextField == 1 {
                mainVC.selectedCityOne = selectedCityName
            } else if selectedTextField == 2 {
                mainVC.selectedCityTwo = selectedCityName
            }
        }

    }


}

This is how my layout looks like. Try it. I just added a continue button too if the user will have to go to another UIViewController after selecting the two cities. enter image description here

enter image description here

Upvotes: 1

Jose Tomas
Jose Tomas

Reputation: 117

If you want to go back to the Parent View, you should be using an unwind-segue.

For that you must create the unwind segue method in the Parent View like this

@IBAction func unwindSegueFromChild(segue: UIStoryboardSegue){
    // This code executes when returning to view
}

And in your child view you must create the unwind segue ctrl+dragging

enter image description here There a dropdown appears and you select unwindSegueFromChild

Once you've done that, you must assign the unwind segue an identifier and programmatically perform it like a normal segue.

Upvotes: 0

David Pasztor
David Pasztor

Reputation: 54706

If you want to segue to MainVC, you should instantiate a view controller from that class in prepare for segue.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let passing = segue.destination as! ViewController
    passing.passedCity2 = sender as! String
}

Change ViewController to whatever the name of your class is for MainVC.

Upvotes: 0

Related Questions