Tom
Tom

Reputation: 1

Is there a way to get the id of a UITableViewCell?

my problem: I want to open some kind of Profil if a user pushes a Button in a Table-View Cell. The Cells Data is downloaded from Parse.

The idea is based on Instagram, if you click on the username-button on Insta the profile from the user who posted the image will open. I want to create the same code, but i can't create the code to get the user. Can you help me?

Heres some code:

import UIKit
import Parse
class HomeController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let reuseIdentifer = "FeedCell"
var delegate: HomeControllerDelegate?
var newCenterController: UIViewController!
let tableView = UITableView()
//Für Parse:
var users = [String: String]()
var comments = [String]()
var usernames = [String]()
var lastnames = [String]()
var imageFiles = [PFFileObject]()
var wischen: UISwipeGestureRecognizer!
var wischen2: UISwipeGestureRecognizer!
override func viewDidLoad() {
    super.viewDidLoad()
        view.backgroundColor = .white
        getData()
        configureNavigationBar()
        configurateTableView()

    wischen = UISwipeGestureRecognizer()
    wischen.addTarget(self, action: #selector(handleMenuToggle))
    wischen.direction = .right
    wischen.numberOfTouchesRequired = 1
    view.addGestureRecognizer(wischen)

    wischen2 = UISwipeGestureRecognizer()
    wischen2.addTarget(self, action: #selector(handleMenuToggle))
    wischen2.direction = .left
    wischen2.numberOfTouchesRequired = 1
    view.addGestureRecognizer(wischen2)
}
@objc func handleMenuToggle() {
    delegate?.handleMenuToggle(forMenuOption: nil)
}

@objc func showProfile() {
    let vc: AProfileViewController!
    vc = AProfileViewController()
    vc.modalPresentationStyle = .fullScreen
    present(vc, animated: true)
}

func configureNavigationBar() {
    navigationController?.navigationBar.barTintColor = .darkGray
    navigationController?.navigationBar.barStyle = .black
    navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.font: UIFont(name: "Noteworthy", size: 22)!, NSAttributedString.Key.foregroundColor: UIColor.white]
    //navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]

    navigationItem.title = "Mobile Job Board"
    navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_menu_white_3x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleMenuToggle))
    navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_mail_outline_white_2x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(showCreateNewArticle))
}
  //MARK: Table View

     //skiped table view configuration

    }
// - MARK: Table view data source

func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // #warning Incomplete implementation, return the number of rows
    return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! FeedCell
        imageFiles[indexPath.row].getDataInBackground { (data, error) in
            if let imageData = data {
                if let imageToDisplay = UIImage(data: imageData) {
                    cell.postImage.image = imageToDisplay
                }
            }
        }
        cell.descriptionLabel.text = comments[indexPath.row]
        cell.userButton.setTitle("\(usernames[indexPath.row]) \(lastnames[indexPath.row])", for: UIControl.State.normal)
        cell.userButton.addTarget(self, action: #selector(showProfile), for: .touchUpInside)
        return cell
}
//skiped
}

Thanks a lot!

Tom

Upvotes: 0

Views: 741

Answers (2)

Josh Homann
Josh Homann

Reputation: 16327

You can generically and in a type safe way get the parent responder of any responder with:

extension UIResponder {
    func firstParent<T: UIResponder>(ofType type: T.Type ) -> T? {
        return next as? T ?? next.flatMap { $0.firstParent(ofType: type) }
    }
}

So:

  1. Get the parent tableviewCell of your button in the target action function
  2. Ask your tableview for the index path
  3. Use the index path.row to index into your users array:
@objc func showProfile(_ sender: UIButton) {
  guard let cell = firstParent(ofType: UITableViewCell.self),
    let indexPath = tableView.indexPath(for: cell) else {
    return
  }
  let user = users[indexPath.row]
  ... do other stuff here ...
}

Upvotes: 0

Matthew Cawley
Matthew Cawley

Reputation: 3008

The issue here is that your button works on a selector and it has no idea about the sender or where it was called from.

I would do this by creating a custom table view cell (e.g. FeedCell) which allows you to set a delegate (e.g. FeedCellDelegate). Set your class as the delegate for the cell and pass into the cell it's current indexPath. You can then return the indexPath in the delegate call.

Example: Note that code has been removed for simplicity and this code has not been tested. This is simply to guide you in the right direction.

View Controller

import UIKit

class HomeController: UIViewController {
    // stripped additional information for example

    func showProfile(_ username: String) {
        let vc: AProfileViewController!
        vc = AProfileViewController()
        vc.username = username
        vc.modalPresentationStyle = .fullScreen
        present(vc, animated: true)
    }
}

extension HomeController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return comments.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! FeedCell

        cell.delegate = self

        cell.descriptionLabel.text = comments[indexPath.row]
        cell.userButton.setTitle("\(usernames[indexPath.row]) \(lastnames[indexPath.row])", for: UIControl.State.normal)

        cell.setIndex(indexPath)

        return cell
    }
}

extension HomeController: FeedCellDelegate {
    func didPressButton(_ indexPath: IndexPath) {
        let userName = usernames[indexPath.row]
        showProfile(username)
    }
}

Feed Cell

import UIKit

protocol FeedCellDelegate {
    didPressButton(_ indexPath: IndexPath)
}

class FeedCell: UICollectionViewCell {

    var delegate: FeedCellDelegate?
    var indexPath: IndexPath
    @IBOutlet weak var userButton: UIButton

    setIndex(_ indexPath: IndexPath) {
        self.indexPath = indexPath
    }

    @IBAction userButtonPressed() {

        if(delegate != nil) {
            delegate?.didPressButton(indexPath)
        }
    }
}

Upvotes: 1

Related Questions