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:
- Automatically Generated Getters and Setters
- get Getter
a. get throws (new in Swift 5.5) - set Setter
- willSet
- 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.