首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >didSet中的循环

didSet中的循环
EN

Stack Overflow用户
提问于 2018-02-13 12:53:29
回答 2查看 583关注 0票数 5

在didSet中使用循环时,我们遇到了这种奇怪的行为。我们的想法是,我们有一个具有树结构的数据类型,并且在每个元素中我们想要存储该项所处的级别。因此,在didSet的level属性中,我们还将设置子级属性。然而,我们意识到,只有当一个人使用forEach,而不是使用for .. in时,这才能起作用。这里有一个简短的例子:

代码语言:javascript
复制
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()

当我运行它时,我得到以下输出:

代码语言:javascript
复制
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

当从一个didSet循环调用subItems属性时,它似乎不会调用for .. in属性的for .. in。有人知道为什么会这样吗?

更新:问题不是没有从init调用didSet。我们在之后更改属性(请参阅最后4行代码),只有两个深度属性中的一个将新值传播给子属性。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-13 13:23:34

如果使用延迟更新任何可选属性或进一步更新已初始化的非可选属性,并且在调用任何超级init方法之后,则将调用您的willSet、didSet等。

代码语言:javascript
复制
        for item in subItems {
            defer{
                item.depthA = depthA + 1
            }
        }

当您使用forEach时,它会与元素进行kindOf“契约”,因为它是一个与不同的实例方法。在循环中,它触发变量的didSet。以上情况适用于我们使用循环的地方,必须手动触发didSet

这解决了我认为的问题。希望能帮上忙!

票数 3
EN

Stack Overflow用户

发布于 2018-02-13 13:16:16

init中,似乎没有调用didSet。

在Swift REPL上尝试了这一行

代码语言:javascript
复制
class A { var a: Int { didSet { print("A") } }; init() { a = 5 } }

然后被称为A()

不调用didSet

代码语言:javascript
复制
A().a = 7

发现didSet被称为

因此,解决方案是创建一个函数(更倾向于final),这使您需要在didSet中添加效果。然后从didSetinit调用它。你可以把这个放到你的课上。

代码语言:javascript
复制
final func updateA() {
    // Do your "didSet" here
}

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

init() {
    a = 5
    updateA()
}

所以在你的情况下:

代码语言:javascript
复制
func updateDepthA() {
    for item in subItems {
        item.depthA = depthA + 1
    }
}

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

...

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

    ...
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48767328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档