简体   繁体   English

Swift 属性观察器问题

[英]Swift property observer issue

I've an issue with my property observer and would like to know a little bit more about the Swift behaviour.我的财产观察员有问题,想了解更多有关 Swift 行为的信息。

I've the following architecture which use callbacks:我有以下使用回调的架构:

A higher lever class更高的杠杆等级

class MyFirstClass : NSScrollView {

var colorDidUpdate: (() -> ())?

var color = NSColor.black {
  didSet { 
    colorDidUpdate?()
  }
 }


override init(frame frameRect: NSRect) {
    super.init(frame: frameRect)
    /* Some init */
    var mySecondClass = MySecondClass(frame: frame)
    colorDidUpdate = mySecondClass.enclosingViewDidUpdateColor
    mySecondClass.color = color
    documentView = mySecondClass
    /* Some other init */
  }

}

Then a second class that act like a link between the first and third class然后是第二类,就像第一类和第三类之间的链接

class MySecondClass {
  var viewColorDidUpdate: (() -> ())?
  var color: NSColor?

  var myThirdClass = MyThirdClass(frame: frame)

  init(frame frameRect: NSRect) {
    /* Some init */
    viewColorDidUpdate = myThirdClass.updateColor
    myThirdClass.color = color
    /* Some other init */
  }

  func enclosingViewDidUpdateColor() {
    viewStyleDidUpdate?()
  }
}

And finally a third class where the draw is done.最后是第三堂课,抽签结束。

class MyThirdClass {
  var color: NSColor?

  func draw(_ dirtyRect: NSRect) {
    guard let color = color else { return }
    // The color is black instead of green.
  }

  /* proerties and functions... */
  func updateColor() {
    functionThatWillTriggerTheDrawFunction() // Will trigger draw function
  }
}

If I set a new color to MyClass property like如果我为 MyClass 属性设置新颜色,例如

var myClass = MyClass()
myClass.color = .green

The printed color is not "green" but it still black...印刷的颜色不是“绿色”,但它仍然是黑色......

I thought that when we were in the didSet scope the variable was already set, am I wrong?我以为当我们在 didSet 范围内时,变量已经设置了,我错了吗?

Should I use an other pattern?我应该使用其他模式吗?

I thought that when we were in the didSet scope the variable was already set, am I wrong?我以为当我们在 didSet 范围内时,变量已经设置了,我错了吗?

No that's true, but something else is happening I guess (although the relevant code doesn't seem to be included)不,那是真的,但我猜还有其他事情正在发生(尽管相关代码似乎没有被包含在内)

A closure as the name suggests closes over variables it uses at the time of its definition.顾名思义,闭closure关闭它在定义时使用的变量。 So you are most likely defining/using the closure at the time where your color still is black.因此,您很可能在颜色仍然黑色时定义/使用闭包。 You can not use a closure to give you the current value of a variable that is captured but you could pass the value into the closure as a parameter.您不能使用闭包为您提供捕获的变量的当前值,但您可以将该值作为参数传递给闭包。 I hope this makes sense.我希望这是有道理的。

If you provide a more complete code sample I can get a better idea about what the problem in your case might be.如果您提供更完整的代码示例,我可以更好地了解您的情况可能存在的问题。

Update (after you provided more code):更新(在您提供更多代码之后):

You are only ever setting the colors of the second and third classes on their init methods.您只是在它们的 init 方法上设置第二个和第三个类的颜色。 You are never updating their color properties when you update the first classes color property.当您更新第一类颜色属性时,您永远不会更新它们的颜色属性。

I am sure the simplification of your presented code is partly to blame, but there are a few things you might want to consider to make things easier to follow:我确信您所提供代码的简化部分是罪魁祸首,但您可能需要考虑一些事情以使事情更容易遵循:

  • Try not saving the color in each and every component separately but rather pass it along as parameters of your functions/methods.尽量不要单独保存每个组件中的颜色,而是将其作为函数/方法的参数传递。 This makes it easier to see, what is happening.这使得更容易看到正在发生的事情。 For example, you could call your change handler colorDidUpdate(to color: NSColor) and pass in the new value.例如,您可以调用更改处理程序colorDidUpdate(to color: NSColor)并传入新值。 This way, at least your second class doesn't need to store the color but rather pass it along into updateColor(_ color: NSColor) which could set the third class' color property and trigger a redraw.这样,至少你的第二个类不需要存储颜色,而是将它传递给updateColor(_ color: NSColor) ,它可以设置第三个类的颜色属性并触发重绘。

  • In general I think it is beneficial to pass in any change to a change handler and not read it from a global state.一般来说,我认为将任何更改传递给更改处理程序而不是从全局状态读取它是有益的。 Try not to store everything but pass along the information you need without storing it in between (if possible).尽量不要存储所有内容,而是传递您需要的信息,而不将其存储在中间(如果可能)。 This makes it easier to see where and how the data and information flows in your app and might indicate problems with the architecture.这样可以更轻松地查看数据和信息在您的应用程序中的流动位置和方式,并可能表明架构存在问题。

It is a bit hard suggesting to architect the entire thing differently since the code is just fragments here, but it looks like you could improve and simplify a bit.建议以不同的方式构建整个事物有点困难,因为这里的代码只是片段,但看起来您可以稍微改进和简化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM