Search code examples
iosswifttableviewuistoryboardsegue

Pass data between TableView and another ViewController in Swift


I am trying to have a list of events presented in a tableView and when the user presses one of the events, it will open another viewController with more information about that particular selection.

This is the tableView that has the options that can be selected :

import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase

class NewsfeedViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    var ref:DatabaseReference!,
        posts = [eventStruct]()
    @IBOutlet weak var tableview: UITableView!
    var propertStruct : (Any)? = nil


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

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

    func loadNews() {
        ref = Database.database().reference()
        ref.child("events").queryOrderedByKey().observe(.childAdded, with: { (snapshot) in

            if let valueDictionary = snapshot.value as? [AnyHashable:String]
            {
                let title = valueDictionary["Title"]
                let location = valueDictionary["Location"]
                let date = valueDictionary["Date"]
                let description = valueDictionary["Description"]
                self.posts.insert(eventStruct(title: title, date: date, location: location, description: description), at: 0)
                self.tableview.reloadData()
            }
        })

    }

    /////////////////////////     Table View Content     \\\\\\\\\\\\\\\\\\\\\\\\\\
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        let label1 = cell.viewWithTag(1) as! UILabel
        label1.text = posts[indexPath.row].title
        let label2 = cell.viewWithTag(2) as! UILabel
        label2.text = posts[indexPath.row].location
        let label3 = cell.viewWithTag(3) as! UILabel
        label3.text = posts[indexPath.row].date
        return cell
    }

    func prepareForSegue(segue: UIStoryboardSegue, sender: eventStruct) {
        let secondViewController = segue.destination as? EventViewController
        secondViewController?.data = sender
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        performSegue(withIdentifier: "showDetails", sender: posts[indexPath.row])
    }
    /////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
}

struct eventStruct {
    let title: String!
    let date: String!
    let location: String!
    let description: String!


}

Here is the DetailsViewController that should display the title of the different option that is selected in the previous tableView:

import UIKit

class EventViewController: UIViewController {

    var data: eventStruct?
    @IBOutlet weak var titleLabel: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()
        print (data?.title as Any)
        self.titleLabel.text = self.data?.title

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

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


    /*
    // 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?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */

}

The problem is that instead of displaying the title that should be stored inside of the struct variable, a nil value is returned all the time.

Could someone tell me what I'm doing wrong? I've tried to follow all the suggestions that were made but nothing works.


Solution

  • Your prepareForSegue must override the UIViewController method which is

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

    Therefore your method in NewsfeedViewController should be

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let secondViewController = segue.destination as? EventViewController
        secondViewController?.data = sender as? eventStruct
    }
    

    it would also be a good idea to add some error checking