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!
CodePudding user response:
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
}
CodePudding user response:
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 YourViewController: 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)
CodePudding user response:
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
}