Ad

Passing Data From Table View Cell Using Button Delegate

I want to pass the data from one view controller to another view controller when the user clicked the button . I am using button with delegate to pass the table view cell values into different view controller view . In second view controller I have two labels and one image to display the fields but the problem is when I clicked the button it is empty.

Here is the cell code .

import UIKit



protocol CellSubclassDelegate: AnyObject {
    func buttonTapped(cell: MovieViewCell)
}

class MovieViewCell: UITableViewCell {
    
    weak var delegate:CellSubclassDelegate?
    
    static let identifier = "MovieViewCell"
    

    @IBOutlet weak var movieImage: UIImageView!
    @IBOutlet weak var movieTitle: UILabel!
    @IBOutlet weak var movieOverview: UILabel!
    
    @IBOutlet weak var someButton: UIButton!
    
    @IBAction func someButtonTapped(_ sender: UIButton) {
        self.delegate?.buttonTapped(cell: self)
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        self.delegate = nil
    }
    
    func configureCell(title: String?, overview: String?, data: Data?) {
        
        movieTitle.text = title
        movieOverview.text = overview
        
        if let imageData = data{
            movieImage.image = UIImage(data: imageData)
           //  movieImage.image = nil
        }
    }
    
}

Here is the first view controller code .

import UIKit

class MovieViewController: UIViewController, UISearchBarDelegate {
    
    @IBOutlet weak var userName: UILabel!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var searchBar: UISearchBar!
    
    
    
    private var presenter: MoviePresenter!
    
    var finalname = ""
    
   var movieTitle = ""
    var movieOverview = ""
    var movieImage : UIImage?
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

       userName.text = "Hello: " + finalname
       setUpUI()
      presenter = MoviePresenter(view: self)
       searchBarText()
       
    }
    private func setUpUI() {
        tableView.dataSource = self
        tableView.delegate = self
    }

    
    
    
   private func searchBarText() {
        searchBar.delegate = self
    }
    
    @IBAction func selectSegment(_ sender: UISegmentedControl) {
        
        if sender.selectedSegmentIndex == 0{
         setUpUI()
        presenter = MoviePresenter(view: self)
        presenter.getMovies()
        }
    }
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchText == ""{
            presenter.getMovies()
        }
        else {
            presenter.movies = presenter.movies.filter({ movies in
                    let originalTitle = movies.originalTitle.lowercased().range(of: searchText.lowercased())
                    let overview = movies.overview.lowercased().range(of: searchText.lowercased())
                    let posterPath = movies.posterPath.lowercased().range(of: searchText.lowercased())
                return (originalTitle != nil) == true || (overview != nil) == true || (posterPath != nil) == true}
                )
        }
        
        tableView.reloadData()
    }
   
    
}

extension MovieViewController: MovieViewProtocol {
    
    func resfreshTableView() {
        tableView.reloadData()
    }
    
    func displayError(_ message: String) {
        let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
        let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
        alert.addAction(doneButton)
        present(alert, animated: true, completion: nil)
    }
    
}

extension MovieViewController: UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        presenter.rows
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
        
        let row = indexPath.row
        let title = presenter.getTitle(by: row)
        let overview = presenter.getOverview(by: row)
        let data = presenter.getImageData(by: row)
        cell.delegate = self
        cell.configureCell(title: title, overview: overview, data: data)
        
       
        
        return cell
    }
    
   func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
        
        let row = indexPath.row
       dc.titlemovie = presenter.getTitle(by: row) ?? ""
       dc.overview = presenter.getOverview(by: row) ?? ""
       dc.imagemovie = UIImage(data: presenter.getImageData(by: row)!)
        self.navigationController?.pushViewController(dc, animated: true)
   }
    
    
}


extension MovieViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
}

extension MovieViewController : CellSubclassDelegate{
    func buttonTapped(cell: MovieViewCell) {
        guard (self.tableView.indexPath(for: cell) != nil) else {return}
            let customViewController = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as? MovieDeatilsViewController
            customViewController?.titlemovie = movieTitle
            customViewController?.imagemovie = movieImage
            customViewController?.overview = movieOverview
        self.navigationController?.pushViewController(customViewController!, animated: true)
                    
                   
    }
    }
 

Here is the details view controller code .

class MovieDeatilsViewController: UIViewController {
    
    
    @IBOutlet weak var movieImage: UIImageView!
    
    @IBOutlet weak var movieTitle: UILabel!
    
    @IBOutlet weak var movieOverview: UILabel!
    
    
    var titlemovie = ""
    var overview = ""
    var imagemovie :UIImage?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        movieTitle.text = titlemovie
        movieOverview.text = overview
        movieImage.image = imagemovie
        
    
        
    }

}

Here is the result when I clicked the button . enter image description here

Ad

Answer

The problem is you don't update you're global properties when selecting each of you're row,
If you pass data over cell delegate and pass you're cell through delegate, you can pass data from cell like:

    customViewController?.titlemovie = cell.movieTitle.text ?? ""
    customViewController?.imagemovie = cell.movieImage.image
    customViewController?.overview = cell.movieOverview.text ?? ""

of course it would be better to pass you're data model to you're cell. and then share that through you're delegate not share you're cell, like:

protocol CellSubclassDelegate: AnyObject {
    func buttonTapped(cell: MovieModel)
}
Ad
source: stackoverflow.com
Ad