Jafett Puga
Jafett Puga

Reputation: 35

UITableView Crashes on Segue to View Controller

Cause of Crash

Click the image above for a brief view of my Segue. My app is a workout tracker. I have a class that makes the workout object with properties such as workout name, description, etc. I have another object that creates the workoutlist, so just an array of Workout objects.

I have a UITableView and a button above it that lets the user create a new workout and adds it to the workoutList array.

The crash happens whenever I click this "create new workout" which segues to a new view controller. I get this error

Crash Error

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var setStepper: UILabel!
    @IBOutlet weak var repStepper: UILabel!

    @IBOutlet weak var workoutName: UITextField!
    @IBOutlet weak var workoutDescription: UITextField!

    @IBOutlet weak var tableView: UITableView!

    var workoutList = WorkoutList().listOfWorkouts

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func stepperCounter(_ sender: UIStepper) {
        if sender.tag == 1 {
            setStepper.text = "\(Int(sender.value))"
        }
        else if sender.tag == 2 {
            repStepper.text = "\(Int(sender.value))"
        }
    }

    @IBAction func addToWorkout(_ sender: Any) {

        //I know this is terrible fixing later. Just for Testing right now
        let newWorkout : Workout = Workout(Name: workoutName.text!, Description: workoutDescription.text!, Sets: Int(setStepper.text!)!, Reps: Int(repStepper.text!)!)

        workoutList.append(newWorkout)
        print(workoutList.count)

    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return workoutList.count

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell()
        cell.textLabel?.text = "Hello"
        return cell

    }

}

Upvotes: 0

Views: 184

Answers (2)

anon
anon

Reputation:

I'd guess that tableView outlet isn't wired up in your storyboard - and that property is an implicitly unwrapped optional. You're promising that it won't be nil.

Upvotes: 0

jensteichert
jensteichert

Reputation: 126

it looks like you are using the same ViewController for both Views in your storyboard. Which means, when you push to the "AddNewWorkoutController" the viewDidLoad expects a tableView - which is not there, because the storyboard didn't build any for this view.

You should create 2 VCS. One for the OverView with the "add new button" and the tableview and another one for actually creating it.

here is a full solution:

create 2 new swift files:

OverViewViewController.swift & NewWorkoutViewController.swift

I just separated your code into 2 VC's:

import UIKit

class OverViewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    var workoutList = WorkoutList().listOfWorkouts

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return workoutList.count

    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell()
        cell.textLabel?.text = "Hello"
        return cell

    }

}

and

import UIKit

class NewWorkoutViewController: UIViewController {

@IBOutlet weak var setStepper: UILabel!
@IBOutlet weak var repStepper: UILabel!

@IBOutlet weak var workoutName: UITextField!
@IBOutlet weak var workoutDescription: UITextField!


override func viewDidLoad() {
    super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

@IBAction func stepperCounter(_ sender: UIStepper) {
    if sender.tag == 1 {
        setStepper.text = "\(Int(sender.value))"
    }
    else if sender.tag == 2 {
        repStepper.text = "\(Int(sender.value))"
    }
}

@IBAction func addToWorkout(_ sender: Any) {

    //I know this is terrible fixing later. Just for Testing right now
    let newWorkout : Workout = Workout(Name: workoutName.text!, Description: workoutDescription.text!, Sets: Int(setStepper.text!)!, Reps: Int(repStepper.text!)!)

    workoutList.append(newWorkout)
    print(workoutList.count)

}

}

Now go into the Storyboard, select the controllers and assign the right classes: like this

After assigning go and connect your tableView to the tableView in the OverView and the 2 actions in your NewWorkout.

This will work.

Upvotes: 1

Related Questions