Passing data into TableView

So i'm trying to pass data through multiple views but having a lot of bother. Essentially i'm trying to create a library/playlist in a table view

I have a table view where the user searches for movies (movie details from API ) and taps their selected movie which then segue to another view controller which displays more info on the users selection.

I'm then attempting to implement an 'add to library' button to then input this data into the table cell in a third view controller. The first segue (to movieDetailsVC) works perfectly however i'm having trouble sending data to the third view controller

I have assumed that in order to display this data in a table view it must first segue to the TableViewCell and then segue again to the final view controller?



MovieSearch VC (initla view controller sends movie data to detail VC)



...

overridefunc prepare(for segue: UIStoryboardSegue, sender: Any?) {
     
        let indexPath = tableView.indexPathForSelectedRow
        let index = indexPath?.row
        let movieDetails = newMovies[index!]
        let movieDetailViewController = segue.destination as! MovieDetailViewController
       
        movieDetailViewController.posterUrl = movieDetails.value(forKeyPath: "backdrop_path") as? String
        movieDetailViewController.coverUrl = movieDetails.value(forKeyPath: "poster_path") as? String
        movieDetailViewController.movieTitle = movieDetails.value(forKeyPath: "title") as? String
        movieDetailViewController.movieRating = movieDetails.value(forKeyPath: "vote_average") as! NSNumber as NSNumber
        movieDetailViewController.movieOverview = movieDetails.value(forKeyPath: "overview") as? String
    }




MovieDetailVC (sends data to tableViewCell)


var newMovies: [NSDictionary] = []

    @IBOutlet var detailView: UIView!
    @IBOutlet weak var posterView: UIImageView!
    @IBOutlet weak var coverView: UIImageView!
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var releaseDateLabel: UILabel!
    @IBOutlet weak var overviewLabel: UILabel!
    @IBOutlet weak var ratingLabel: UILabel!
   
   
    var posterUrl: String!
    var coverUrl: String!
    var movieTitle: String!
    var movieReleaseDate: String!
    var movieOverview: String!
    var movieRating: NSNumber!
...
attempts to send var movieTitle defined above to libraryTableViewCell (libMovieTitle)
// destination should be LibraryViewController ??
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let LibraryTableViewCell = segue.destination as! LibraryMovieTableViewCell
        LibraryTableViewCell.libMovieTitle = movieTitle
    }

TableViewCell(attempts to send data to final ViewController)



  
 
class LibraryMovieTableViewCell: UITableViewCell {

    @IBOutlet weak var cellTitleLabel: UILabel!
    
    var libMovieTitle: String?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
   func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let LibraryMovieViewcontroller = segue.destination as! LibraryMovieViewController
        LibraryMovieViewController.libraryTitle = cellTitleLabel
        
      }
}

LibraryViewController (attempts to display sent data in table)



class LibraryMovieViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
   
    @IBOutlet weak var tableView: UITableView!
   
    var libraryMovies: [NSDictionary] = []
    let libraryTitle: String?
   
     override func viewDidLoad() {
         super.viewDidLoad()
         tableView.dataSource  = self
        tableView.delegate = self
         // Do any additional setup after loading the view.
     }
   
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return libraryMovies.count
    }
   
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
        let libraryCell = tableView.dequeueReusableCell(withIdentifier: "libCell", for: indexPath) as! LibraryMovieTableViewCell
        libraryCell.textLabel!.text = libraryTitle
    
        return libraryCell
   
    }
}

At Present I receive an error:

Instance member 'libraryTitle' cannot be used on type 'LibraryMovieViewController'

at:

LibraryMovieViewController.libraryTitle = cellTitleLabel

Replies

Could you post the real code ? This one is edited with a lot of ** showing it is probably not actual code.


You should also show more code, notable the different prepare for segues.


Thiis code does not work:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     let LibraryTableViewCell = segue.destination as! LibraryMovieTableViewCell 
     LibraryTableViewCell.cellTitleLabel.text = movieTitle 
} 


- you cannot set directly the IBOutlet in the destination.

- you have to create a property in the destination to hold the value to pass

     var movieTitle: String?


But the destination is not a cell.

It is the TableViewController


So please provide more complete and accurate details on the code.

Thanks for your reply, I have updated and added as much relevant code in the project as possible,


In the TableViewCell

I receive an error on the following line:

" Instance member 'libraryTitle' cannot be used on type 'LibraryMovieViewController' "

   LibraryMovieViewController.libraryTitle = movieTitle

As said before, you have to send data to the ViewController. Not to the cell directly.


So you send from a first tableView cell (A) to the destination controller LibraryMovieViewController (B).

In LibraryMovieViewController, you load the cells from its dataSource

It is not clear in the code what is the content of a cell in LibraryMovieViewController


What are

var libraryMovies: [NSDictionary] = []

let libraryTitle: String! = nil


How are they populated ?

What do you expect by declaring a constant for libraryTitle ?

And it seems you give the same content to all cells ??

You should probably load the cell from the dictionary (if I guess correctly what you want to do)


Prepare for segue in A should load the dataSource of the destination B (probably the dictionary).


Please clarify.

"As said before, you have to send data to the ViewController. Not to the cell directly."

I'm not sure I follow, are you saying that i should remove the prepare function in TableViewCell and instead directly send it from MovieDetailVc to LibraryViewController?


var libraryMovies: [NSDictionary] = [] is useless and was used in experimentation to see what fits


I do however have a

var newMovies: [NSDictionary] = []


on the first table view to declare the movie details used on the first view and MovieDetailVC, is it possible to reference it in a third view controller?


"What do you expect by declaring a constant for libraryTitle" -> I assumed we had to cretae a property in the destination to hold the value to pass, like in your first comment

I can't follow the back and forth in Swift, I only do Objectove C. Here is a simple observation for your consideration:


There are two issues here, one is getting the data to the data source and the other is displaying data in the table. The table is usually in the same class as the data source. The table gets that data in your method cellForRowAtIndexPath. How does that data source get the data?


I get data to various classes by using a static model object. One static model object that is always your friend is NSUserDefaults. Another is to create a class using the following (in Objective C):


static Model *singleton;

@implementation Model

+(Model *)sharedInstance{
    if (singleton == nil){
        singleton = [[Model alloc] init];
        [singleton initTheSingleton];  // this is my init method
    }
    return singleton;
}


Then I call Model from any class using:


[Model sharedInstance].someObject;
//or
[[Model sharedInstance] some Method];


In your case I would load the data for the table into that Model and retrieve it from my data source.

Ok, to make sure we understand, let's return to the complete set up.


FirstVC: MovieSearch

I have a table view where the user searches for movies (movie details from API )

That's MovieSearch, correct ?

and taps their selected movie which then segue to another view controller which displays more info on the users selection.

When you tap in a cell, that selects a movie

SecondVC: MovieDetailViewController

You segue and pass this with other values in movieDetailViewController.movieTitle


I'm then attempting to implement an 'add to library' button to then input this data into the table cell in a third view controller.

ThirdVC: LibraryMovieViewController

Where is this button ? In each cell ? Or a global one for the ViewController ?

I cannot see it in code

How have you defined the segue to LibraryMovieViewController ?

Most impoprtant : what is the datasource for the tableView in this third VC ?


The first segue (to movieDetailsVC) works perfectly however i'm having trouble sending data to the third view controller

I have assumed that in order to display this data in a table view it must first segue to the TableViewCell and then segue again to the final view controller?

That's where you are confusing.

First segue: where is it called ? In didSelectRow ?

Then you go to secondVC.

You should have a segue defined globally from secondVC to thirdVC.

Then the button will call this segue.

In the prepare, you should pass a movie reference. to the dataSource.


What is not clear is where you keep track of all the movies in Library ? The dictionary is empty by now in thirdVC, so useless.