Adrian Navarro
Adrian Navarro

Reputation: 135

Passing data through tableView using the button clicked

I have a button, which is the username. When i click the username, i want to pass the data through, and i also want to grab the userid of the selected username. I know it's not working because i know i'm not technically selecting a row. Any tips on how to get the row index of the button, thank you.

Here is my ViewController

import UIKit
import Firebase
import FirebaseAuth
import FirebaseStorage
import FirebaseDatabase

class DiscussionListTableViewController: UITableViewController, PostCellDelegate {
    var postRef: DatabaseReference!
    var storageRef: StorageReference!
    var posts = [Posts]()

    @IBAction func profileAction(_ sender: Any) {
       if Auth.auth().currentUser == nil {
            performSegue(withIdentifier: "toLogin", sender: self)
            print("no user logged in")
        } else {
            performSegue(withIdentifier: "toProfile", sender: self)
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        postRef = Database.database().reference().child("posts")
        postRef.observe(DataEventType.value, with: { (snapshot) in
            var newPosts = [Posts]()

            for post in snapshot.children {
                let post = Posts(snapshot: post as! DataSnapshot)
                newPosts.insert(post, at: 0)
            }
            self.posts = newPosts
            self.tableView.reloadData()
        }, withCancel: {(error) in
            print(error.localizedDescription)
        })
    }

    override func viewDidLoad() {
        tableView.rowHeight = 160
        super.viewDidLoad()
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
        cell.usernameLabel.setTitle(posts[indexPath.row].username, for: .normal)
        cell.postDescriptionLabel.text = posts[indexPath.row].description
        cell.postTitleLabel.text = posts[indexPath.row].title
        let image = posts[indexPath.row]
        cell.userProfilePic.sd_setImage(with: URL(string: image.userImageStringUrl), placeholderImage: UIImage(named: "1"))
        cell.postImageView.sd_setImage(with: URL(string: image.postImageStringUrl), placeholderImage: UIImage(named: "1"))

        cell.delegate = self

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        performSegue(withIdentifier: "addComment", sender: self)
    }

    func usernameClicked() {
        performSegue(withIdentifier: "viewProfile", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "addComment" {
            let commentVC = segue.destination as! CommentTableViewController
            let indexPath = tableView.indexPathForSelectedRow!
            let selectedIndex = posts[indexPath.row]
            commentVC.selectedPost = posts[indexPath.row]
            commentVC.postDescription = selectedIndex.description
            commentVC.postImageUrl = selectedIndex.postImageStringUrl
            commentVC.postTitle = selectedIndex.title
            commentVC.postUsername = selectedIndex.username
            commentVC.profilePicUrl = selectedIndex.userImageStringUrl
        } else {
            if segue.identifier == "viewProfile" {
                let viewProfileVC = segue.destination as? ViewProfileViewController
                let indexPath = tableView.indexPathForSelectedRow
                let selectedIndex = posts[indexPath.row]
                viewProfileVC?.username = selectedIndex.username
                viewProfileVC?.userid = selectedIndex.userid
            }
        }
    }
}

Guessing my error is here since I'm not actually selecting a row when I click the button:

 if segue.identifier == "viewProfile" {
    let viewProfileVC = segue.destination as?     ViewProfileViewController
    let indexPath = tableView.indexPathForSelectedRow
    let selectedIndex = posts[indexPath.row]
    viewProfileVC?.username = selectedIndex.username
    viewProfileVC?.userid = selectedIndex.userid
}

Here is my TableViewCell

import UIKit
import Foundation

protocol PostCellDelegate {
    func usernameClicked()
}

class PostTableViewCell: UITableViewCell {
    var delegate: PostCellDelegate?

    @IBOutlet weak var userProfilePic: UIImageView!

    @IBOutlet weak var usernameLabel: UIButton!
    @IBOutlet weak var postImageView: UIImageView!
    @IBOutlet weak var postDescriptionLabel: UILabel!
    @IBOutlet weak var postTitleLabel: UILabel!

    @IBAction func usernameButtonAction(_ sender: Any) {
        print("Username clicked")
        self.delegate?.usernameClicked()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
}

Here is the view controller I'm trying to pass the data to.

import UIKit
import Firebase
import FirebaseDatabase
import FirebaseStorage
import FirebaseAuth

class ViewProfileViewController: UIViewController {
    var clickedUserRef: DatabaseReference!
    var userid = ""
    var username = ""
}

Upvotes: 2

Views: 1796

Answers (1)

rmaddy
rmaddy

Reputation: 318794

You need to pass the cell as a parameter to the usernameClicked delegate method.

Then then the table view controller can ask the table view what the index path of the cell is. Then from the index path you can get the data you need.

Update the protocol:

protocol PostCellDelegate {
    func usernameClicked(_ cell: PostTableViewCell)
}

Update the button handler:

@IBAction func usernameButtonAction(_ sender: Any) {
    print("Username clicked")
    self.delegate?.usernameClicked(self)
}

Add a property to your `DiscussionListTableViewController:

var clickedPath: IndexPath? = nil

Update the method in the view controller:

func usernameClicked(_ cell: PostTableViewCell) {
    if let indexPath = self.tableView.indexPath(for: cell) {
        clickedPath = indexPath
        performSegue(withIdentifier: "viewProfile", sender: self)
    }
}

Then in your prepare(for:), replace the use of:

let indexPath = tableView.indexPathForSelectedRow!

with:

if let indexPath = clickedPath {
    // get the row
    // access the posts data
}

Upvotes: 3

Related Questions