Search code examples
swiftxcodeuinavigationcontrolleruitabbarcontroller

Aftar i click on cell its pass me 2 views, how can i fix it?


I have an app that starts with tab bar with 3 items,2 of them is just a regular view controller and one of them is navigation controller and after him is table view,when I click on a cell I want to pass 2 String to the labels and to pass to a new view controller to show the label's,my problem is that after I click on the cell its looks like its jump 2 view controller's until the view controller that I want, and in the first time I didn't see my data that I pass, only after I press to come back to the table view controller(here I need to back to him from 2 view controllers), please help me to fix my code, I want to pass the data and move to a new view controller and when I want to come back to the table view I need to click just back

//Table view controller, before of him I have a navigation controller

//The identifier of the segue is "Details"

import UIKit

class HistoryTableViewController: 
UIViewController,UITableViewDelegate,UITableViewDataSource {


@IBOutlet weak var historyTableView: UITableView!
var historyArray = [history]()
var foods = ["Milk","Honey","Salt","Bread","Banana"]

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = historyTableView.dequeueReusableCell(withIdentifier: "cell") as? HistoryCellViewController
        else {return UITableViewCell()}

    //  cell.ageLabel.text = String(format:"%f", historyArray[indexPath.row].age)
    //  cell.genderLabel.text = historyArray[indexPath.row].gender
    // cell.ageLabel.text = String(format:"%f", 23)
    cell.genderLabel.text = foods[indexPath.row]
    cell.ageLabel.text = foods[indexPath.row]
    // cell.genderLabel.text = "Bar"
    //cell.historyImage.image = nil
    return cell

}

var selectedAge:String = " "
var selectedGender:String = " "
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    selectedAge = self.foods[indexPath.row]
    selectedGender = self.foods[indexPath.row]
    performSegue(withIdentifier: "Details", sender: self)


}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "Details"{
        let vc = segue.destination as! HistoryDetailsViewController
        vc.age = selectedAge
        vc.gender = selectedGender
    }
}


func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == UITableViewCell.EditingStyle.delete {

        foods.remove(at: indexPath.row)
        historyTableView.reloadData()
    }

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

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

}

//view controller that I want to pass after a click on a cell

 import UIKit

 class HistoryDetailsViewController: UIViewController {
 @IBOutlet weak var ageLabel: UILabel!
 @IBOutlet weak var genderLabel: UILabel!
 var age:String?
 var gender:String?
 override func viewDidLoad() {
    super.viewDidLoad()
      ageLabel.text = self.age
      genderLabel.text = self.gender
    // Do any additional setup after loading the view.
}

 //
 //    @IBAction func Back(_ sender: UIBarButtonItem) {
 //        
//      //  self.tabBarController?.selectedIndex = 0
//    }



}

Solution

  • First of all, in tableView(_:cellForRowAt:) you're typecasting the dequeued cell to HistoryCellViewController.

    My question is - what is the type of HistoryCellViewController? Is it a UITableViewCell or something else? In case it is a UITableViewCell you must rename it to something more relevant like HistoryCell. It is a bit confusing.

    Approach-1:

    Now coming to the actual problem you're facing. Instead of using the segue, try pushing the HistoryDetailsViewController manually like so,

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let controller = self.storyboard?.instantiateViewController(withIdentifier: "HistoryDetailsViewController") as? HistoryDetailsViewController {
            controller.age = self.foods[indexPath.row]
            controller.gender = self.foods[indexPath.row]
            self.navigationController?.pushViewController(controller, animated: true)
        }
    }
    

    There is no need to extra variables - selectedAge and selectedGender.

    Approach-2:

    In case you want to do it with the segue itself, then don't call performSegue(withIdentifier:sender:) in tableView(_:didSelectRowAt:), i.e. remove the below line of code,

    performSegue(withIdentifier: "Details", sender: self)
    

    This is because, the "Details" segue is being executed twice - once via storyboard and another via the above line of code.