Особенности наблюдателей за свойствами
Иногда бывает необходимо выполнить дополнительные операции при изменении значений свойств. Чтобы отловить события, используются наблюдатели willSet/didSet, в работе с которыми есть нюансы.
Рассмотрим пример:
import UIKit
class Object {
var color = UIColor.greenColor() {
didSet {
color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
}
}
private(set) var red = CGFloat()
private(set) var green = CGFloat()
private(set) var blue = CGFloat()
private(set) var alpha = CGFloat()
var point = CGPoint() {
didSet {
print("Point changed to \(point)")
}
}
var name = NSMutableString() {
didSet {
print("Name changed to \(name)")
}
}
init() {
color = UIColor.redColor()
}
}
Первое — наблюдатели не вызываются при задании значений по умолчанию, а также в инициализаторе:
let object = Object()
print("Red: \(object.red), green: \(object.green), blue: \(object.blue), alpha \(object.alpha)")
// Output: Red: 0.0, green: 0.0, blue: 0.0, alpha 0.0
И второе — изменение (мутация) свойств значений не ссылочных типов (структур и перечислений) реализуется через перезапись экземпляра на новый, содержащий обновления, поэтому мутация провоцирует вызов наблюдателей. Для ссылочных типов (объектных классов) такого не происходит:
object.point = CGPoint(x: 10, y: 10)
object.point.x = 20
// Output: Point changed to (10.0, 10.0)
// Point changed to (20.0, 10.0)
object.name = NSMutableString(string: "'The new name'")
object.name.setString("Changed name")
// Output: Name changed to 'The new name'