0

I have two view controllers as UITableViewController and DestinationViewController. The content of DestinationViewController should change according to tapped UITableViewCell. I tried this tutorial but this one didn't make sense. How can I determine which cell is tapped and how can I perform segue when the cell tapped?

EDIT:

UITableViewController:

let days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

var myIndex: Int?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    table1View.deselectRowAtIndexPath(indexPath, animated: true)
    myIndex = indexPath.row
    self.performSegueWithIdentifier("showClassesForSchedule", sender: nil)
}

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "showClassesForSchedule":
            let destinationViewController = segue.destinationViewController as? ScheduleAsClassTableViewController// set here нour destionation VC
            if destinationViewController != nil {
                destinationViewController?.tableArray.append(days[myIndex!])
                destinationViewController?.tableArray = days
                print(days[myIndex!])
            }
        default: break
        }
    }
}


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

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

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("scheduleDaysTextCellIdentifier", forIndexPath: indexPath) as UITableViewCell

    let row = indexPath.row
    cell.textLabel?.text = days[row]

    return cell
}

DestinationViewController:

    var tableArray = [String]()
    @IBOutlet var table1View: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
        print(tableArray)
    }
    @IBOutlet weak var comingLabelAsNormalView: UILabel!

    @IBOutlet weak var comingName: UILabel!

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

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return tableArray.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = table1View.dequeueReusableCellWithIdentifier("scheduleDayClassIdentifier", forIndexPath: indexPath) as UITableViewCell

        let row = indexPath.row
        cell.textLabel?.text = tableArray[row]

        return cell
    }
do it better
  • 4,627
  • 6
  • 25
  • 41

2 Answers2

1

You can perform a segue in tableView didSelectRowAtIndexPath. Then in prepareForSegue method set your destinationVC and pass needed data.

Code:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "yourSegueIdentifier":
            let destinationViewController = segue.destinationViewController as? UIViewController // set here нour destionation VC
            if destinationViewController != nil {
                destinationViewController?.passedData = yourData
            }
        default: break
        }
    }
}

Don't forget to create a segue and set the identifier. If you have questions ask in comments.

Here is your tableView didSelectRowAtIndexPath:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
    // save indexPath to any Int variable
    myIndex = indexPath.row
    self.performSegueWithIdentifier("yourSegueIndentifier", sender: nil)
}
mkz
  • 2,302
  • 2
  • 30
  • 43
  • In which function am I need to perform segue? – do it better Sep 13 '15 at 09:24
  • When you say perfromSegueWithIdentifier it will call prepareForSegue method where you can set your data according to your indexPath.row – mkz Sep 13 '15 at 09:26
  • I imported the code in your post but I've a problem. The problem is, in `prepareForSegue` function I've passed the button's name that have tapped. But in destination view controller I've printed the passed data and I got nil.?? – do it better Sep 13 '15 at 16:25
  • In your `prepareForSegue` method you said `destinationViewController?.tableArray.append(days[myIndex!])` `destinationViewController?.tableArray = days` A you sure you want to do this? If you want to pass just the selected day you have to leave only this line: `destinationViewController?.day = days[myIndex!]` – mkz Sep 14 '15 at 21:43
  • And don't forget to create `String` variable in DestinationViewController. `var day: String!` – mkz Sep 14 '15 at 21:45
  • I've added `var day:String?` and `destinationViewController?.day = days[myIndex!]` and also added print(day) in viewDidLoad() in destination view controller. Unfortunately I still got nil. – do it better Sep 14 '15 at 21:52
  • Check your segue `identifier` to match in `prepareForSegue` method and in `storyboard`, maybe you've made a mistake. Also, you can check if `prepareForSegue` it called properly? One more thing you can to do is to `println(index)` in `prepareForSegue` to see if it is corrent. – mkz Sep 14 '15 at 21:55
  • As you said, I added `print("DONE")` and `print("OK")` respectively to `destinationViewController != nil` and case `"showClassesForSchedule":`. After that, only "OK" printed to console. I don't know why but `destinationViewController` comes nil. – do it better Sep 15 '15 at 15:11
  • Have you checked the `showClassesForSchedule` segue in `storyboard`. Does it set properly from your mainVC to `ScheduleAsClassTableViewController`? Also check it's identifier should match to `showClassesForSchedule'. – mkz Sep 15 '15 at 18:35
  • I'd. Besides, the segue launches. The problem roots in the prepareForSegue function's if part. Only the if part doesn't work. I don't know why but it doesn't. – do it better Sep 15 '15 at 18:42
  • Try to write this `let destinationViewController = segue.destinationViewController as! UIViewController`. Replace `as?` with `as!` and remove if statement at all. Remove this `if destinationViewController != nil {`. – mkz Sep 15 '15 at 18:44
  • But I need to declare the target view controller. – do it better Sep 15 '15 at 19:42
  • GOT IT :) Finally I've noticed that I've a navigation controller between first and second controller(sorry for that:( ] I've used the link below. http://stackoverflow.com/questions/28573635/destinationviewcontroller-segue-and-uinavigationcontroller-swift – do it better Sep 15 '15 at 19:46
1

There are a few ways of doing this. I'd recommend using segues. This method doesn't require didSelectRowAtIndexPath.

Firstly, create a segue by right clicking and dragging from your prototype cell to the next view controller and choosing Show:

enter image description here

Then give the segue an identifier:

enter image description here

Next you need a reference to the index path of the particular cell that was tapped. You can do this in prepareForSegue. Try something like this:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "detail" {
        if let cell = sender as? UITableViewCell{
            if let indexPath = self.tableView.indexPathForCell(cell) {
                // get a reference to the next view controller so you can pass data in
                var nvc = segue.destinationViewController as! NewViewController

                // set properties on the next view controller using the acquired cell's index
                nvc.name = names[indexPath.row]
            }
        }
    }
}

The above code checks for the segue identifier. sender in this case is the UITableViewCell that the user tapped. The next two lines try to get a reference to this cell and its associated indexPath. You can then use indexPath.row or indexPath.section as requied before you segue in order to access relevant data. Then a reference is obtained to the next view controller (for which you should have created an associated class and hooked it up in interface builder) and whatever properties you would like to set can then be set on this reference.

Gordonium
  • 3,389
  • 23
  • 39