Почему не сработал?

Во многих примерах didSet Я вижу на SO, этот код вернется 0Однако я не могу заставить его возвращать что-либо кроме исходного значения. Что я делаю неправильно?

стриж

struct Circle {
    var radius: Double {
        didSet {
            if radius < 0 {
                radius = 0
            }
        }
    }
}

var circ = Circle(radius: -25)

print(circ.radius)

Выход

-25

5 ответов

Решение

didSet не вызывается во время инициализации, только после. Если вы хотите проверить данные во время инициализации, ваш инициализатор должен это сделать.

Если вы добавите:

circ.radius = -50
print(circ.radius)

вы увидите, что он работает так, как вы ожидаете, и результат будет 0.0,

Вы можете убедиться didSet в init, если вы положите его в defer заявление. Также работает в deinit,

class Circle {
    var radius: Double {
       didSet {
          if radius < 0 {
             radius = 0
          }
       }
    }

    init(radius: Double) {
        defer { self.radius = radius }
    }
}

Как пишет Пол в комментариях наблюдателей за недвижимостью didSet а также willSet не вызываются во время инициализации значения.

Если вы хотите вызвать их для значения также при инициализации, вы можете добавить вызов функции, чтобы переустановить radius свойство после того, как оно было изначально установлено в инициализаторе:

struct Circle {
    var radius: Double {
        didSet {
            if radius < 0 {
                radius = 0
            }
        }
    }

    init(radius: Double) {
        self.radius = radius
        setRadius(radius) // <-- this will invoke didSet
    }

    mutating func setRadius(radius: Double) {
        self.radius = radius
    }
}

var circ = Circle(radius: -25)

print(circ.radius) // 0.0

Также вы можете использовать lazy и init (radius ....

      struct Circle {
    lazy var radius: Double = 0.0 {
        didSet {
            print("didSet called")
            if radius < 0 {
                radius = 0
            }
        }
    }
    init(radius:Double) {
        self.radius = radius
    }
}

Используйте для этого init:

struct Circle {
    var radius: Double

    init(radius: Double) {
        self.radius = radius < 0 ? 0 : radius
    }
}

var circ = Circle(radius: -25)

print(circ.radius)

0.0
Другие вопросы по тегам