2

I have created this table with 3 sections and 7 rows. The code is shown below

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet var subjectTabelView: UITableView!

var slSubject = ["English Lang&Lit", "Chinese Lang&Lit", "Economics"]
var hlSubject = ["Mathematics", "Chemistry", "Biology"]
var tokSubject = ["Theory of Knowledge"]

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    subjectTabelView.dataSource = self
    subjectTabelView.delegate = self
}

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

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

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 0{
        return hlSubject.count
    }else if section == 1{
        return slSubject.count
    }else {
        return tokSubject.count
    }

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let subjectCell = tableView.dequeueReusableCellWithIdentifier("idSubjectCell", forIndexPath: indexPath) as! UITableViewCell

    if indexPath.section == 0 {
        subjectCell.textLabel?.text = hlSubject[indexPath.row]
    } else if indexPath.section == 1{
        subjectCell.textLabel?.text = slSubject[indexPath.row]
    } else {
        subjectCell.textLabel?.text = tokSubject[indexPath.row]
    }

    return subjectCell
}

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if section == 0 {
        return "HL"
    } else if section == 1{
        return "SL"
    } else {
        return "ToK"
    }
}



}

What do I have to do to make every cell in this table pushes a new view controller when it is tapped? The picture of my storyboard is shown below. In my storyboard, my view controller, I have already created a navigation controller, and made the view controller that has the table the rootViewController. And for now, my tableView has only one prototype cell and one cell identifier.

Thank you!

Shawn Clarke
  • 35
  • 1
  • 1
  • 5

3 Answers3

3

Suppose your "locationVC" is:

class LocationVC: UIViewController {

    @IBOutlet weak var fromWhereLabel: UILabel!
    //This can be changed when creating this UIViewController
    var textToShow : String?

    override func viewWillAppear(animated: Bool) {
        if let textToShow = textToShow {
            fromWhereLabel.text = textToShow
        }
    }
}

then, just adding function below to your code in ViewController named UIViewController (that should have a better name ;-)) you can achieve your goal.

 func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
      //if such cell exists and destination controller (the one to show) exists too..
        if let subjectCell = tableView.cellForRowAtIndexPath(indexPath), let destinationViewController = navigationController?.storyboard?.instantiateViewControllerWithIdentifier("locationVC") as? LocationVC{
            //This is a bonus, I will be showing at destionation controller the same text of the cell from where it comes...
            if let text = subjectCell.textLabel?.text {
                destinationViewController.textToShow = text
            } else {
                destinationViewController.textToShow = "Tapped Cell's textLabel is empty"
            }
          //Then just push the controller into the view hierarchy
          navigationController?.pushViewController(destinationViewController, animated: true)
        }
     }

You will be able to have a LocationVC UIViewController launched every time you tap a cell, and it will have some value to prove it right. :)

Hope it Helps!

UPDATE: Code and Instructions below are for allowing to launch different UIViewControllers after tap on cells

1.- Let's create a class that will be the parent for every one of our new UIViewControllers (the ones we are willing to go from our tableview cell's tap):

public class CommonDataViewController: UIViewController {
//Here we are going to be putting any data we want to share with this view
  var data: AnyObject?
}

2.- Let's create some sort of Navigation rules, just to be organised ;-)

enum Navigation: Int {
    case vc1 = 0, vc2 = 1, vc3 = 2, vc4 = 3
    //How many rules we have (for not to exceed this number)
    static let definedNavigations = 4
    //This must return the identifier for this view on the Storyboard
    func storyboardIdentifier() -> String {
        //for this example's sake, we have a common prefix for every new view controller, if it's not the case, you can use a switch(self) here
        return "locationVC_\(self.rawValue + 1)"
    }
}

Now, let's build upon previous code:

3.- For clarity, let's change a little our previous LocationVC (that for this example, will have an Storyboard Identifier with the text "locationVC_1")

class LocationVC: CommonDataViewController {

    @IBOutlet weak var fromWhereLabel: UILabel!

    //This is optional, but improves clarity..here we take our AnyObject? variable data and transforms it into the type of data this view is excepting 
    var thisVCReceivedData: String? {
        return data as? String
    }

    override func viewWillAppear(animated: Bool) {
        if let textToShow = thisVCReceivedData {
            fromWhereLabel.text = textToShow
        }
    }
}

4.- Now, we trigger all of this in our didSelectRowAtIndexPath function.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //Just to avoid tapping on a cell that doesn't have an UIViewController asociated
    if Navigation.definedNavigations > indexPath.row {
        //The view's instance on our Navigation enum to which we most go after tapping this cell
        let nextView = Navigation(rawValue: indexPath.row)!
        //The identifier of the destination CommonDataViewController's son in our Storyboard
        let identifier = nextView.storyboardIdentifier()
        //If everything exists...
        if let subjectCell = tableView.cellForRowAtIndexPath(indexPath), let destinationViewController = navigationController?.storyboard?.instantiateViewControllerWithIdentifier(identifier) as? CommonDataViewController {

            //here you can use a switch around "nextView" for passing different data to every View Controller..for this example, we just pass same String to everyone
            if let text = subjectCell.textLabel?.text {
                destinationViewController.data = text
            } else {
                destinationViewController.data = "Tapped Cell's textLabel is empty"
            }
            navigationController?.pushViewController(destinationViewController, animated: true)
        }
    }
}

Notice that you can achieve same results using protocols and delegate approach, this is just simpler to explain

Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
  • Hi! I have a question, would this show the content of the cell in the viewController? For example on twitter, when you click on a tweet, it opens the tweet in a different viewController, but only showing the tweet and allows you to comment on it. – Bruno Recillas Aug 14 '15 at 23:48
  • @HugoAlonso, so do I create a new file LocationVCViewController.swift? would this solution allow me to create 7 different view controllers for my 7 different cells? Thank you – Shawn Clarke Aug 15 '15 at 08:08
  • @BrunoRecillas yes, you can do something like that with this approach, you just pass an instance of your tweet, data, etc instead of just text in `.textToShow` and you are ready to go. – Hugo Alonso Aug 17 '15 at 14:15
  • @ShawnClarke Now, that's something would be great to know in advance, sorry for not catching it early ;-) (just for you to know, even if you can't post images, you can link to them)..so, to answer your question: Just creating a `LocationVCViewController` or `LocationVC` wouldn't be enough. For that matter, clarify me something: **you know in advance, which row (indexPath.row) will be in place for every new ViewController you want to show?** in other words, your cells are always at the same place? ..ex: the one to lead to newVC_3 is always at row 3, newVC_2 at row 2, etc..? – Hugo Alonso Aug 17 '15 at 14:21
  • Could you be a little bit more specific? Please? @HugoAlonso – Bruno Recillas Aug 17 '15 at 22:01
  • @BrunoRecillas suppose you have view **A** and view **B**, **A** presents **B**. **B** has a placeholder variable, in this example is `.textToShow` of type `String` but can be of any type. Then, before you present **B** and after creating it´s instance. You can pass any value into that variable. And, as when you present your `UIViewController` **B** you can implement your update for such data in the `viewWillAppear` of **B**. Showing this way data corresponding to what was selected on **A**. – Hugo Alonso Aug 17 '15 at 22:28
  • So since I'm using a textView, in the new ViewController, in the `viewWillAppear` I just call the class of the UITableView, and select the `textView.textToShow` ? – Bruno Recillas Aug 17 '15 at 22:38
  • @BrunoRecillas please go ahead and code it, you will notice that there is only one way to achieve this without relying in **delegates**, I will update my comment for just an extra detail that may be confusing you. – Hugo Alonso Aug 17 '15 at 22:43
  • I can't edit but my last comment, so I will edit here an except from my previous comment : ¨...You can pass any value into that variable **from inside tableView didSelectRowAtIndexPath function of A (as shown on this answer)**.**Then** when you present your UIViewController B you can implement your update for such data in the viewWillAppear of B **(ex. colouring with a different color, updating some text, etc)**. Showing this way **the** data corresponding **to the cell that** what was selected on A.¨ – Hugo Alonso Aug 17 '15 at 22:50
  • Okay so I'm working on it, and first I didn't add any data, just tried to see if after pushing the cell it would show the viewController and it does. Now, I have created a textView in the new ViewController so the text is displayed there. I'm just having a little problem here with `destinationViewController` is that the new ViewController? or the new ViewController class? by new ViewController I mean the ViewController storyboard ID? – Bruno Recillas Aug 17 '15 at 23:05
  • Okay so I figured it out. I made it work, fixed the errors I got, but now it crashes. Is it because I'm using a textView instead of a label? Or is it because I'm using Parse.com database and I didn't transfer the data? – Bruno Recillas Aug 17 '15 at 23:43
  • @HugoAlonso hi yes for now my cells will always be at the same place – Shawn Clarke Aug 19 '15 at 00:33
  • Ok, I will be updating soon with a solution for your case. – Hugo Alonso Aug 19 '15 at 14:18
0

Well to push a view controller in a UINavigationController you just use this code:

ViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:@"locationVC"];
[self.navigationController pushViewController:viewController animated:YES];

The method you are looking for is this one:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    ViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:@"locationVC"];
    [self.navigationController pushViewController:viewController animated:YES];
}
MSU_Bulldog
  • 3,501
  • 5
  • 37
  • 73
  • this code is in Objective-C, the question is about how to achieve this in swift – Hugo Alonso Aug 14 '15 at 16:00
  • @Hugo It says in his question that he already created a navigation controller. – dmarsi Aug 14 '15 at 16:03
  • @MSU_Bulldog Hi thank you for the suggestion, but what if I want different cell to push different views, which means there will be more multiple identifiers? Thank you – Shawn Clarke Aug 15 '15 at 07:41
  • What I want to do with the app is that, I want a different view controller for all the subjects and the app would allow the users to key in their grades for each subject and the app will graph the values keyed in. – Shawn Clarke Aug 15 '15 at 08:13
0

You could use prepareForSegue method. You just need to set up the destination view. or the didselectrowatindexpath prepareForSegue code looks like :

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "nameofTheSegue"
{
    if let destinationVC = segue.destinationViewController as? OtherViewController{
        // do whatever you want with the data you want to pass.
    }
}
}
Lamour
  • 3,002
  • 2
  • 16
  • 28