Creating the Item Class

Your table view needs some rows to display. Each row in the table view will display an item with information such as a name, serial number, and value in dollars.

Create a new Swift file named Item. In Item.swift, define the Item class and give it four properties.

Listing 9.2  Creating the Item class (Item.swift)

import Foundation
import UIKit

class Item {
    var name: String
    var valueInDollars: Int
    var serialNumber: String?
    let dateCreated: Date
}

Notice that serialNumber is an optional String, necessary because an item may not have a serial number. Also, notice that none of the properties has a default value. Without these default values, Xcode will report an error that Item has no initializers. You will need to give these properties their values in a designated initializer.

Custom initializers

You learned about struct initializers in Chapter 2. Initializers on structs are fairly straightforward because structs do not support inheritance. Classes, on the other hand, have some rules for initializers to support inheritance.

Classes can have two kinds of initializers: designated initializers and convenience initializers.

A designated initializer is a primary initializer for the class. Every class has at least one designated initializer. A designated initializer ensures that all properties in the class have a value. Once it ensures that, a designated initializer calls a designated initializer on its superclass (if it has one).

Implement a new designated initializer on the Item class that sets the initial values for all the properties.

Listing 9.3  Adding a designated initializer (Item.swift)

import UIKit

class Item {
    var name: String
    var valueInDollars: Int
    var serialNumber: String?
    let dateCreated: Date

    init(name: String, serialNumber: String?, valueInDollars: Int) {
        self.name = name
        self.valueInDollars = valueInDollars
        self.serialNumber = serialNumber
        self.dateCreated = Date()
    }
}

This initializer takes in arguments for the name, serialNumber, and valueInDollars. Because the argument names and the property names are the same, you must use self to distinguish the property from the argument.

Now that you have implemented your own custom initializer, you can never use the free init() initializer that classes have. The free initializer is useful when all your class’s properties have default values and you do not need to do additional work to create the new instance. The Item class does not satisfy these criteria, so you have declared a custom initializer for the class. Now that you have a custom initializer, if you were to go back and add default values to each of Item’s properties, you still would not be able to use the free initializer.

Every class must have at least one designated initializer, but convenience initializers are optional. You can think of convenience initializers as helpers. A convenience initializer always calls another initializer on the same class. Convenience initializers are indicated by the convenience keyword before the initializer name.

Add a convenience initializer to Item that creates a randomly generated item.

Listing 9.4  Adding a convenience initializer (Item.swift)

convenience init(random: Bool = false) {
    if random {
        let adjectives = ["Fluffy", "Rusty", "Shiny"]
        let nouns = ["Bear", "Spork", "Mac"]

        let randomAdjective = adjectives.randomElement()!
        let randomNoun = nouns.randomElement()!

        let randomName = "(randomAdjective) (randomNoun)"
        let randomValue = Int.random(in: 0..<100)
        let randomSerialNumber =
            UUID().uuidString.components(separatedBy: "-").first!

        self.init(name: randomName,
                  serialNumber: randomSerialNumber,
                  valueInDollars: randomValue)
    } else {
        self.init(name: "", serialNumber: nil, valueInDollars: 0)
    }
}

If random is true, the instance is configured with a random name, serial number, and value. Notice that you are force unwrapping the call to randomElement(). Why does this method return an optional element? If the array is empty, there are no elements to return. But you know the adjectives and nouns arrays are not empty, because you declared them a few lines above, and so it is safe to force unwrap this optional.

Finally, at the end of both branches of the conditional, you call through to the designated initializer for Item. Convenience initializers must call another initializer on the same type, whereas designated initializers must call a designated initializer on the superclass.

The Item class is ready for work. In the next section you will display an array of Item instances in a table view.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset