SwiftUI - 更改@Published 结构时是否可以触发 didSet? [英] SwiftUI - is it possible to get didSet to fire when changing a @Published struct?

查看:15
本文介绍了SwiftUI - 更改@Published 结构时是否可以触发 didSet?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚更新到 XCode 11.4,但我的一些代码已停止工作.我在 ObservableObject 中有一些 @Published 结构变量.以前,当我更新结构上的属性时,didSet 方法会在已发布的属性上触发,但现在情况不再如此.在 Swift 的最新更新中,这种行为是否有可能在设计上有所改变?

I have just updated to XCode 11.4 and some of my code has stopped working. I have some @Published struct variables in an ObservableObject. Previously, when I updated properties on the struct, the didSet method would fire on the published property, but that's not the case anymore. Is it possible that this behaviour has changed by design in the latest update to Swift?

这是一个简单的例子:


import SwiftUI

struct PaddingRect {
  var left: CGFloat = 20
  var right: CGFloat = 20
}

final class SomeStore : ObservableObject {
  @Published var someOtherValue: String = "Waiting for didSet"

  @Published var paddingRect:PaddingRect = PaddingRect() {
    didSet {
      someOtherValue = "didSet fired"
    }
  }
}

struct ObserverIssue: View {
  @ObservedObject var store = SomeStore()

  var body: some View {
    VStack {
      Spacer()

      Rectangle()
        .fill(Color.yellow)
        .padding(.leading, store.paddingRect.left)
        .padding(.trailing, store.paddingRect.right)
        .frame(height: 100)

      Text(store.someOtherValue)

      HStack {
        Button(action: {
          // This doesn't call didSet
          self.store.paddingRect.left += 20

          // This does call didSet, ie. setting the whole thing
//          self.store.paddingRect = PaddingRect(
//            left: self.store.paddingRect.left + 20,
//            right: self.store.paddingRect.right
//          )

        }) {
          Text("Padding left +20")
        }

        Button(action: {
          self.store.paddingRect.right += 20
        }) {
          Text("Padding right +20")
        }
      }

      Spacer()
    }
  }
}

struct ObserverIssue_Previews: PreviewProvider {
    static var previews: some View {
        ObserverIssue()
    }
}

属性更新,但 didSet 没有触发.

The property updates, but didSet does not fire.

是否可以获取结构体的嵌套属性来触发发布者的didSet方法?

Is it possible to get nested properties of a struct to trigger the didSet method of the publisher?

推荐答案

属性观察者观察属性.问题来自与属性包装器相关的新 Swift 语法.在您的情况下,您尝试观察 Published 的值(这是一个定义专用属性包装器的结构)是否确实发生了变化,而不是包装的属性的值.

The property observer observes the property. The trouble goes from new Swift syntax related to property wrappers. In your case you try to observe if value of Published (which is a struct defining the specialized property wrapper) did change, not the value of the wrapped property.

如果你需要监控PaddingRect中的左值或右值,直接观察这个值即可.

If you need to monitor left or right values in PaddingRect, simply observe this values directly.

import SwiftUI


struct PaddingRect {
    var left: CGFloat = 20 {
        didSet {
            print("left padding change from:", oldValue, "to:", left)
        }
    }
    var right: CGFloat = 20 {
        didSet {
            print("right padding change from:", oldValue, "to:", right)
        }
    }
}

final class SomeStore : ObservableObject {
    @Published var someOtherValue: String = "Waiting for didSet"
    @Published var paddingRect:PaddingRect = PaddingRect()
}

struct ContentView: View {
    @ObservedObject var store = SomeStore()

    var body: some View {
        VStack {
            Spacer()

            Rectangle()
                .fill(Color.yellow)
                .padding(.leading, store.paddingRect.left)
                .padding(.trailing, store.paddingRect.right)
                .frame(height: 100)

            Text(store.someOtherValue)

            HStack {
                Button(action: {
                    // This doesn't call didSet
                    self.store.paddingRect.left += 20

                    // This does call didSet, ie. setting the whole thing
                    self.store.paddingRect = PaddingRect(
                        left: self.store.paddingRect.left + 20,
                        right: self.store.paddingRect.right
                    )

                }) {
                    Text("Padding left +20")
                }

                Button(action: {
                    self.store.paddingRect.right += 20
                }) {
                    Text("Padding right +20")
                }
            }

            Spacer()
        }
    }
}

struct ContentView_Preview: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

或者利用已发布的预计值是发布商并将下一个修饰符应用于任何视图

Or take the advantage that Published projected value is Publisher and aply next modifier to any View

.onReceive(store.$paddingRect) { (p) in
            print(p)
        }

这篇关于SwiftUI - 更改@Published 结构时是否可以触发 didSet?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆