2

I'm having issues with appending an optional value to an array in Swift. The view I'm writing is for the creation of a routine for the gym. However my Routine object is not being instantiated as it should be.

I have experience with other programming languages but I am fairly new to Swift, and optionals.

My ViewController contains an optional variable:

var routine: Routine?

Where the Routine class contains:

name: String
exerciseList: [String]()
numOfSets: [Int]()

When I am preparing it to send the newly created routine to my other ViewController, I take the values from user input to edit the fields of the object.

let name = routineName.text ?? ""
let numberOne = Int(numOfSetsOne.text ?? "0") //numOfSetsOne is a text label
routine?.exerciseList.append(selectedExerciseOne!) //Haven't tested to see if this works yet
routine?.numOfSets[0] = numberOne! //This line is not working 
routine = Routine(name: name)

To try a little debugging I put print statements on either side of the line like so:

print ("numberOne Value: \(numberOne!)")
routine?.numOfSets[0] = numberOne!
print ("numOfSets[0] Value: \(routine?.numOfSets[0])")

I expected the output from the second print statement to be identical to the first. However the terminal output:

numberOne Value: 3
numOfSets[0] Value: nil

Does anyone know what has gone wrong here? Thanks

3
  • 6
    var routine: Routine? is initially nil. You probably want to assign routine = Routine(name: name) before calling the methods. Commented Apr 11, 2019 at 11:49
  • @MartinR This was spot on. Thank you Commented Apr 11, 2019 at 11:57
  • A routine is better modelled by a struct. Routines don't have identity. If you have two routines named "5x5 deadlifts", with a exercise "deadlift", and sets: [5, 5, 5, 5, 5], then they're identical. I would switch Routine over to a struct, then I would take advantage of the member wise initializer to do a one-shot intitialization, in which the initializer takes name, exerciseList, and numOfSets as params, and sets them all. Commented Apr 11, 2019 at 13:52

2 Answers 2

3

You have declared a property that may contain a Routine, but you have not assigned an instance of Routine to that property before trying to use it.

This means that, for example,

routine?.numSets[0] = numberOne! 

doesn't do anything - routine is nil and so the statement is skipped.

You should create an appropriate init function for your Routine class and use that to create a new Routine and assign it to routine

For example:

class Routine {
    var name: String
    var exerciseList = [String]()
    var numberOfSets = [Int]()

    init(named: String) {
        self.name = named
    }
}

Then you can say

let name = routineName.text ?? ""
let numberOne = Int(numOfSetsOne.text ?? "0") 
self.routine = Routine(named: name)
self.routine?.numberOfSets.append(numberOne!)

Coordinating related arrays can get a bit messy, so I would use a single array:

struct ExerciseSet {
    let exerciseName: String
    let sets: Int
}


class Routine {
    var name: String
    var exerciseList = [ExerciseSet]()

    init(named: String) {
        self.name = named
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

Your Routine is not initialised before its being assigned value

try

let name = routineName.text ?? ""
let numberOne = Int(numOfSetsOne.text ?? "0") 

routine = Routine(name: name)

routine?.exerciseList.append(selectedExerciseOne!) 
routine?.numOfSets[0] = numberOne!  

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.