skip to Main Content

I am very very new to Swift programming and I am growing to dislike it very much. I am not grasping it aa easily as other languages.

I have a project I am working on and I cannot figure out what is wrong or why its isn’t working.

In one view, I have a table view that has a cell. I am using an array to store all the values that I want to be stored in the corresponding elements in the table view.

When the user clicks on an individual cell in the table view, it will bring them to another view displaying other elements of the movie (runtime, image, director and year).

I have a template that I am using to code this and I think I have done everything correctly, but when I run the app, nothing shows.

I just want the table cells to show on startup, when I run the app. I can even troubleshoot myself if I can just have the table cells show.

Since I am so new to this language and XCode, I am having trouble navigating the IDE to find my issues. On top of much I am already struggling with Swift.

I could really use the help, if possible!

Here is all the code I have done:

    import UIKit

    class ViewController: UIViewController,
    UITableViewDelegate,
    UITableViewDataSource  {
    
    let movieList = ["Step Brothers", "Pulp Fiction", "Ali", "Harry Potter"]
    let yearList = ["2008", "1994", "2001", "2001"]
    let images = ["step_brothers", "pulp_fiction", "ali", "harry_potter3"]

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return movieList.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let tempCell: TableViewCell = tableView.dequeueReusableCell(withIdentifier:         
                 "cell") as! TableViewCell
        
        tempCell.movieTitleLabel.text = movieList[indexPath.row]
        tempCell.movieYearLabel.text = yearList[indexPath.row]
        tempCell.movieImage.image = UIImage(named: images[indexPath.row] + ".jpeg")
        
        return tempCell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        let detailVC:MovieDetailViewController = self.storyboard?.instantiateViewController(withIdentifier: "MovieDetailViewController") as! MovieDetailViewController
       // assign the values to the local variable declared in ProductDetailViewController Class
        detailVC.movieImage = UIImage(named: images[indexPath.row] + ".jpeg")!
      
        // make it navigate to ProductDetailViewController
        self.navigationController?.pushViewController(detailVC, animated: true)
     }  
    }

This is for the individual cell in the table view:

import UIKit

class TableViewCell: UITableViewCell {

@IBOutlet weak var movieTitleLabel: UILabel!

@IBOutlet weak var movieYearLabel: UILabel!

@IBOutlet weak var movieImage: UIImageView!


override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

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

    // Configure the view for the selected state
 }
}

This is the MovieDetailViewController:

class MovieDetailViewController: UIViewController {

    @IBOutlet weak var movieDetailImage: UIImageView!
    
    @IBOutlet weak var runtimeLabel: UILabel!
    
    @IBOutlet weak var yearDetailLabel: UILabel!
    
    @IBOutlet weak var directorDetailLabel: UILabel!
    
    var runtime: String!  // holds the product name
    var year: String!  // holds the price
    var movieImage: UIImage! // holds the product image
    var director: String!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        movieDetailImage.image = movieImage
        runtimeLabel.text = runtime
        yearDetailLabel.text = year
        directorDetailLabel.text = director

        // Do any additional setup after loading the view.
    }
    /*
    // 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.destination.
        // Pass the selected object to the new view controller.
    }
    */
   }

This is the error shown in the terminal, but there are no actual errors in the code:

2022-11-14 17:39:28.232645-0500 Exercise01[25678:1217794] [Storyboard] Unable to find method -[(null) TableViewCell] 2022-11-14 17:39:28.259975-0500 Exercise01[25678:1217794] [Assert] UINavigationBar decoded as unlocked for UINavigationController, or navigationBar delegate set up incorrectly. Inconsistent configuration may cause problems. navigationController=<UINavigationController: 0x141012400>, navigationBar=<UINavigationBar: 0x142106160; frame = (0 47; 0 50); opaque = NO; autoresize = W; layer = <CALayer: 0x600001d72280>> delegate=0x141012400

I can throw in the AppDelegate and SceneDelegate if you need it, just let me know.

Thank you everyone, again! I greatly appreciate the help!

3

Answers


  1. I have tried your code, and I didn’t get any errors, I hope you have set the data source and delegate of table view. Just add this to your viewDidLoad()

    override func viewDidLoad() {
    super.viewDidLoad()
    
      tableView.delegate = self
      tableView.dataSource = self
    }
    
    Login or Signup to reply.
  2. I’d first recommend to get rid of Storyboards, they’re error prone and debugging is a hell.

    Your problem: I don’t see you connecting the UITableView to the ViewController (with an IBOutlet if you use storyboards).
    What you need to do is setting the UITableViewDelegate and the UITableViewDataSource for that UITableView

    class ViewController: UIViewController,
    UITableViewDelegate,
    UITableViewDataSource  {
    
    let movieList = ["Step Brothers", "Pulp Fiction", "Ali", "Harry Potter"]
    let yearList = ["2008", "1994", "2001", "2001"]
    let images = ["step_brothers", "pulp_fiction", "ali", "harry_potter3"]
    
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
    }
    
    Login or Signup to reply.
  3. I think that the delegate and datasource aren’t the only errors…
    This is an example (complete code) for how you can do it programmatically:

    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    let movieList = ["Step Brothers", "Pulp Fiction", "Ali", "Harry Potter"]
        let yearList = ["2008", "1994", "2001", "2001"]
        let images = ["step_brothers", "pulp_fiction", "ali", "harry_potter3"]
    
    let tableView = UITableView() // declare tableView
    
        override func viewDidLoad() {
            super.viewDidLoad()
            view.backgroundColor = .white
    
            tableView.backgroundColor = .white
            tableView.translatesAutoresizingMaskIntoConstraints = false // disable defaults constrints
            // set delegate and datasource
            tableView.delegate = self
            tableView.dataSource = self
            tableView.register(TableViewCell.self, forCellReuseIdentifier: "cell") // register your cell
            
            view.addSubview(tableView)
            tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
            tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
            tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return movieList.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            
            let tempCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell // get cellId and indexPath
            tempCell.movieTitleLabel.text = movieList[indexPath.row]
            tempCell.movieYearLabel.text = yearList[indexPath.row]
            tempCell.movieImage.image = UIImage(named: images[indexPath.row])
            
            return tempCell
        }
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80 // height of single row
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let cell = tableView.cellForRow(at: indexPath) as! TableViewCell // This is your cell in didSelectRow to obtain objects in there
        
        let detailVC = MovieDetailViewController()
        
        detailVC.movieImage = cell.movieImage.image ?? UIImage()
        detailVC.runtimeLabel.text = cell.movieTitleLabel.text
        detailVC.yearDetailLabel.text = cell.movieYearLabel.text
        
        navigationController?.pushViewController(detailVC, animated: true)
     }
    }
    

    this is your cell:

    class TableViewCell: UITableViewCell {
    
    let movieTitleLabel = UILabel()
    let movieYearLabel = UILabel()
    let movieImage = UIImageView()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.backgroundColor = .white
        
        movieTitleLabel.textColor = .black
        movieYearLabel.textColor = .black
        
        movieTitleLabel.translatesAutoresizingMaskIntoConstraints = false
        movieYearLabel.translatesAutoresizingMaskIntoConstraints = false
        movieImage.translatesAutoresizingMaskIntoConstraints = false
                   
        contentView.addSubview(movieImage)
        movieImage.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        movieImage.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
        movieImage.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        movieImage.widthAnchor.constraint(equalTo: contentView.heightAnchor).isActive = true
        
        let stackView = UIStackView(arrangedSubviews: [movieTitleLabel, movieYearLabel])
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.translatesAutoresizingMaskIntoConstraints = false
        
        contentView.addSubview(stackView)
        stackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
        stackView.leadingAnchor.constraint(equalTo: movieImage.trailingAnchor, constant: 10).isActive = true
        stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10).isActive = true
        stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
     }
    }
    

    this is your movieDetailController:

    class MovieDetailViewController: UIViewController {
    
    let movieDetailImage = UIImageView()
    let runtimeLabel = UILabel()
    let yearDetailLabel = UILabel()
    
    let runtime = String()  // holds the product name
    var year = String()  // holds the price
    var movieImage = UIImage() // holds the product image
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        movieDetailImage.translatesAutoresizingMaskIntoConstraints = false
        runtimeLabel.translatesAutoresizingMaskIntoConstraints = false
        yearDetailLabel.translatesAutoresizingMaskIntoConstraints = false
        
        movieDetailImage.image = movieImage
        movieDetailImage.contentMode = .scaleAspectFill
        
        runtimeLabel.textColor = .black
        runtimeLabel.textAlignment = .center
        yearDetailLabel.textColor = .black
        yearDetailLabel.textAlignment = .center
        
        view.addSubview(movieDetailImage)
        movieDetailImage.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        movieDetailImage.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        movieDetailImage.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        movieDetailImage.heightAnchor.constraint(equalTo: movieDetailImage.widthAnchor).isActive = true
        
        let stackView = UIStackView(arrangedSubviews: [runtimeLabel, yearDetailLabel])
        stackView.axis = .vertical
        stackView.distribution = .fillEqually
        stackView.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(stackView)
        stackView.topAnchor.constraint(equalTo: movieDetailImage.bottomAnchor).isActive = true
        stackView.leadingAnchor.constraint(equalTo: movieDetailImage.leadingAnchor).isActive = true
        stackView.heightAnchor.constraint(equalToConstant: 60).isActive = true
        stackView.trailingAnchor.constraint(equalTo: movieDetailImage.trailingAnchor).isActive = true
     }
    }
    

    And This is the result (there isn’t any array for directorDetailLabel)

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search