A getter in Swift allows access to a property, and a setter allows a property to be set. This post presents an overview of getters and setters, and examples of some Swift features related to getters and setters:

  1. Automatically Generated Getters and Setters
  2. get Getter
    a. get throws (new in Swift 5.5)
  3. set Setter
  4. willSet
  5. didSet
    a. ‘didSet’ cannot be provided together with a getter
    b. ‘willSet’ cannot be provided together with a getter
    c. ‘didSet’ cannot be provided together with a setter
    d. ‘willSet’ cannot be provided together with a setter

Automatically Generated Getters and Setters

When an instance property is defined in Swift using var, a getter and setter is automatically generated:

class Notes {
     var canSave = false
}

notes = Notes()
notes.canSave // Getter is available
notes.canSave = true // Setter is available

When an instance property is defined in Swift using let, only a getter is available:

class Store {
     let canOrder = false
}

store = Store()
store.canOrder // Getter is available

// This will not compile and cause the error:
// "Cannot assign to property 'canSave' 
//  is a 'let' constant"
store.canOrder = true

get Getter

One way to implement a variable property without an exposed setter is to indicate a variable as private(set):

class Store {
    private(set) var canOrder = false
}

// Create a store instance
store = Store()
store.canOrder // Getter is available

// This will not compile and cause the error:
// "Cannot assign to property: 'canOrder' 
//  setter is inaccessible"
store.canOrder = true

Another way to implement a variable property without an exposed setter is to use get. Often get is used to expose a getter to a private property:

class Store {
    private var _canOrder = false
    var canOrder: Bool {
        get { return _canOrder }
    }
}

// Create a store instance
store = Store()
store.canOrder // Getter is available

// This will not compile and cause the error:
// "Cannot assign to property: 'canOrder' 
//  is a get-only property"
store.canOrder = true

get throws (new in Swift 5.5)

Starting in Swift 5.5, throws is available for getters defined with get:

class Notes {
    func isDatabaseAvailable() throws -> Bool { 
        /* ... */ 
    }

    var canSave: Bool {
        get throws {
            return try isDatabaseAvailable()
        }
    }
}

notes = Notes()

do {
    if try notes.canSave {
        // Handle logic
    }
}
catch {
    // Handle error
}

set Setter

The set keyword can be used to implement an explicit setter in Swift. Often set is used to expose a setter for a private property and apply additional logic:

class Notes {
    func isDatabaseAvailable() -> Bool { 
        /* ... */ 
    }

    private var _canSave = false
    var canSave: Bool {
        get { return _canSave }
        set { 
            if isDatabaseAvailable() { 
                _canSave = newValue
            }
        }
    }
}

willSet

If explicit getters and setters using get and set are not defined, willSet can be used to take action before a new value is set for a property:

class Notes {
    func storePreviousSaveValue(_ canSave: Bool) {}
    var canSave = false {
        willSet {
            // Inside of willSet, the property 
            // canSave will be the old value,
            // before a new one is set
            storePreviousSaveValue(canSave)
        }
    }
}

// Creates an instance of notes with
// notes.canSave initialized to false
notes = Notes()

// willSet will be called while notes.canSave is
// false, so storePreviousSaveValue is called 
// with false, then notes.canSave is set to true
notes.canSave = true

didSet

If explicit getters and setters using get and set are not defined, didSet can be used to take action after a new value is set for a property:

class Notes {
    @IBOutlet var saveButton: UIButton?

    var canSave = false {
        didSet {
            // Inside of didSet, the property 
            // canSave will have the new value
            saveButton?.userInteractionEnabled = canSave
        }
    }
}

// Creates an instance of notes with
// notes.canSave initialized to false
notes = Notes()

// didSet will be called after notes.canSave is
// set to true, so saveButton?.userInteractionEnabled
// will be set to true
notes.canSave = true

'didSet' cannot be provided together with a getter

If only didSet and get are implemented, didSet will never be called because a get-only property cannot be set:

var canSave: Bool {
    // This causes the compiler error:
    // "‘didSet’ cannot be provided 
    //  together with a getter"
    get { /* ... */ }
    didSet { /* ... */ }
}

'willSet' cannot be provided together with a getter

If only willSet and get are implemented, willSet will never be called because a get-only property cannot be set:

var canSave: Bool {
    // This causes a compiler error:
    // "'willSet' cannot be provided 
    //  together with a getter"
    get { /* ... */ }
    willSet { /* ... */ }
}

'didSet' cannot be provided together with a setter

If only didSet and set are implemented, didSet should instead be implemented inside of the set setter:

var canSave: Bool {
    // This causes a compiler error:
    // "'didSet' cannot be provided 
    //  together with a setter"
    set { /* ... */ }
    didSet { /* ... */ }
}

// This is a better alternative:
var canSave: Bool {
    set { 
        canSave = newValue

        // Add code for didSet here,
        // after a new value is set
    }
}

'willSet' cannot be provided together with a setter

If only willSet and set are implemented, willSet should instead be implemented inside of the set setter:

var canSave: Bool {
    // This causes a compiler error:
    // "'willSet' cannot be provided 
    //  together with a setter"
    set { /* ... */ }
    willSet { /* ... */ }
}

// This is a better alternative:
var canSave: Bool {
    set { 
        // Add code for willSet here,
        // before a new value is set

        canSave = newValue
    }
}

Swift Getters and Setters

That’s it! By using get, set, willSet, and didSet you can implement getters and setters in Swift.