Hinges in didSet

We encountered this odd behavior when using loops in didSet. The idea was that we have a data type with a tree structure, and in each element we wanted to keep the level at which this element is included. Thus, in the didSet attribute, levelwe also set the level attribute of the children. However, we realized that this only works if used forEach, and not when used for .. in. Here is a quick example:

class Item {

    var subItems: [Item] = []
    var depthA: Int = 0 {
        didSet {
            for item in subItems {
                item.depthA = depthA + 1
            }
        }
    }
    var depthB: Int = 0 {
        didSet {
            subItems.forEach({ $0.depthB = depthB + 1 })
        }
    }

   init(depth: Int) {
        self.depthA = 0

        if depth > 0 {
            for _ in 0 ..< 2 {
                subItems.append(Item(depth: depth - 1))
            }
        }
   }

   func printDepths() {
        print("\(depthA) - \(depthB)")

        subItems.forEach({ $0.printDepths() })
   }
}

let item = Item(depth: 3)
item.depthA = 0
item.depthB = 0
item.printDepths()

When I run this, I get the following output:

0 - 0
1 - 1
0 - 2
0 - 3
0 - 3
0 - 2
0 - 3
0 - 3
1 - 1
0 - 2
0 - 3
0 - 3
0 - 2
0 - 3
0 - 3

It looks like it will not call the didSet attribute of the subItems attribute when it is called from the loop for .. in. Does anyone know why this is so?

UPDATE: , didSet init. (. 4 ), depth

+4
2

defer, - , , , - -init-, willSet, didSet ..

        for item in subItems {
            defer{
                item.depthA = depthA + 1
            }
        }

forEach, kindOf "" , .. , didSet . , , didSet

, . , !

+2

, init didSet .

Swift REPL

class A { var a: Int { didSet { print("A") } }; init() { a = 5 } }

A()

didSet

A().a = 7

, hasSet

, , (, final), didSet. didSet, init. .

final func updateA() {
    // Do your "didSet" here
}

var a: Int {
    didSet {
        updateA()
    }
}

init() {
    a = 5
    updateA()
}

, :

func updateDepthA() {
    for item in subItems {
        item.depthA = depthA + 1
    }
}

var depthA: Int = 0 {
    didSet {
        updateDepthA()
    }
}

...

init(depth: Int) {
    self.depthA = 0
    updateDepthA()

    ...
0

Source: https://habr.com/ru/post/1693574/


All Articles