4

I have a tableView populated with information from a JSON array. When I click on that cell, it segues into a DetailsViewController where it should display

  1. a label that displays the text of the cell that was clicked on (in my case it is title, or entry name)
  2. a label that shows the time corresponding to that cell's title
  3. a label that shows id corresponding to that cell's title. All this information (ex. time, id) come from my JSON array.

I've already got #1 working, #2 is what I need help on (and I'm sure after I figure that out I can do the id label easily). I'm using didSelectRowAtIndexPath for updating the time label and the program runs fine but the time label isn't updated with info. The label doesn't even show up.

Here is my code in my tableViewController file:

class EarthTableViewController: UITableViewController {
    var info = [AppModel]()



    func getEarthquakeInfo(completion: (results : NSArray?) ->Void ){

        DataManager.getEarthquakeDataFromFileWithSuccess {
            (data) -> Void in

                let json = JSON(data: data)


                if let JsonArray =  json.array {

                    for appDict in JsonArray {
                        var ids: String? = appDict["id"].stringValue
                        var title: String? = appDict["title"].stringValue
                        var time: String? = appDict["time"].stringValue
                        var information = AppModel(idEarth: ids, title: title, time: time)

                        self.info.append(information)
                        completion(results: self.info)
                    }


            }

        }



    }


    override func viewDidLoad() {
        super.viewDidLoad()
        getEarthquakeInfo { (info) in
            self.tableView.reloadData()
        }
    }




    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->   UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath) as UITableViewCell
        let infoArray = self.info
        cell.textLabel!.text = info[indexPath.row].title
        return cell

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

        if segue.identifier == "SEGUE" {
            let vc = segue.destinationViewController as DetailsViewController
            let cell = (sender as UITableViewCell)
            let title = cell.textLabel!.text
            vc.titleData = title

        }
    }




    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

                let time = info[indexPath.row].time
                let destinationVC = DetailsViewController()
                destinationVC.timeData = time


    }

My DetailsViewController file:

class DetailsViewController: UIViewController {


    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var idLabel: UILabel!

    @IBOutlet weak var timeLabel: UILabel!
    var titleData: String!
    var idData: String!
    var timeData: String!

    override func viewDidLoad() {
        super.viewDidLoad()
        let earthInfo = EarthTableViewController()
        titleLabel.text = titleData
        idLabel.text = idData
       timeLabel.text = timeData
    }

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



}

And just in case here is my AppModel.swift file that I used:

class AppModel: NSObject, Printable {
    let idEarth: String
    let title: String
    let time: String


    override var description: String {
        return "ID: \(idEarth), TITLE: \(title), TIME: \(time), \n"
    }

    init(idEarth: String?, title: String?, time: String?) {
        self.idEarth = idEarth ?? ""
        self.title = title ?? ""
        self.time = time ?? ""
    }

}

Any help would be appreciated.

UPDATE WITH ANSWER: Using the help from the people's comments down below I was able to figure out the answer to my own question. Turns out, I didn't even need to use didSelectRowAtIndexPath. The reason why I added that in the first place was because when tried to do let time = info[indexPath.row].time in prepareForSegue it didn't work since I didn't add the code that was needed for me to do that. Now all the labels are displaying info properly.

 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {

        if segue.identifier == "SEGUE" {
            let vc = segue.destinationViewController as DetailsViewController
            let cell = (sender as UITableViewCell)
            let title = cell.textLabel!.text
            vc.titleData = title

            if let indexPath = self.tableView.indexPathForSelectedRow(){
            let time = info[indexPath.row].time
                println("\(time)")
                vc.timeData = time
            let id = info[indexPath.row].idEarth
                vc.idData = id

            }
        }
    }
videoperson
  • 139
  • 1
  • 12

1 Answers1

4

This seems to a simple mistake regarding how you're passing the data between the two view controllers.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if segue.identifier == "SEGUE" {
        let vc = segue.destinationViewController as DetailsViewController
        let cell = (sender as UITableViewCell)
        let title = cell.textLabel!.text
        vc.titleData = title
    }
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let time = info[indexPath.row].time
    let destinationVC = DetailsViewController()
    destinationVC.timeData = time
}

The issue is in the fact that you are sending the information to a UIViewController that isn't being presented. In didSelectRowAtIndexPath: you're initializing a view controller and sending the data to it correctly, but that specific instance is never shown. To fix this, you have a few options. You can either choose to continue using an Action Segue and pass the data within the segue using performSegueWithIdentifier: & prepareForSegue:, or you can choose to utilize instantiateViewControllerWithIdentifier: and manually present said view controller.

Jeffrey
  • 1,271
  • 2
  • 15
  • 31
  • Alright now I think I understand, but if I were to take the Action segue option and use performSegueWithIdentifier, would it be under didSelectRowAtIndexPath? (I've tried doing that but I think I'm doing it wrong because I get an error) Could you give me an example of how I would approach that? Thanks for the help. – videoperson Apr 28 '15 at 00:50
  • 1
    Personally, what I would do, would to create a global variable and each time didSelectRowAtIndexPath: is called, I would update the variable just before the performSegueWithIdentifier: method, and then I would simply pass the global variable to the DetailViewController. @videoperson – Jeffrey Apr 28 '15 at 00:57
  • 1
    I'm not sure why he's doing things so complicated. He sends the time info in `didSelectRowAtIndexPath` and then he sends the title in prepareForSegue, using a cell. Probably not the complete code since he mentioned #1 and #2 were working, but there is no sign of him changing view ever in this code. The ID info is never passed and a new instance of `EarthTableViewController` is created, why? You have an array `info`, why don't you just send that using `indexPath` as subscript? Just like `destinationVC.infoSingle = info[indexPath.row]` – Eendje Apr 28 '15 at 01:02
  • @JacobsonTalom Very true. Regardless, as I said above, take it with a grain of salt. – Jeffrey Apr 28 '15 at 01:04
  • @jkaufman seems he understands the concept, but just confused how to properly segueing the DetailedViewController. – Eendje Apr 28 '15 at 01:08