【问题标题】:Swift KVO binding not updatedSwift KVO 绑定未更新
【发布时间】:2023-04-10 09:02:01
【问题描述】:

在我的 macOS 应用程序中,我想将文本与可视 NSDatePicker 结合起来。因此,我制作了一个自定义的 NSDatePicker,点击时会显示一个弹出窗口。

文本选择器使用绑定检查器链接到变量:

我的问题是,虽然文本选择器在弹出窗口中选择某些内容时会在视觉上更新,但绑定值 (prop_dateTime) 没有更新。

我尝试过的一些方法:

class TextualAndVisualDatePickerElement: NSDatePicker {
    [...]
    func showPopover(sender: NSDatePicker) {
        //using Bond
        self.reactive.objectValue.bidirectionalBind(to: visualDatePicker.reactive.objectValue)

        //using KVO
        visualDatePicker.bind(.value, to: self, withKeyPath: "dateValue", options: [:])

        //using setValue
        _ = self.reactive.objectValue.observeNext(with: {self.setValue($0, forKey: "dateValue")})
        _ = visualDatePicker.reactive.objectValue.observeNext(with: {sender.setValue($0, forKey: "dateValue")})

        //using willChange
        _ = self.reactive.objectValue.observeNext(with: {visualDatePicker.willChangeValue(forKey: "dateValue"); visualDatePicker.dateValue = $0 as! Date; visualDatePicker.didChangeValue(forKey: "dateValue")})
        _ = visualDatePicker.reactive.objectValue.observeNext(with: {self.willChangeValue(forKey: "dateValue"); self.dateValue = $0 as! Date; self.didChangeValue(forKey: "dateValue")})

    }
    [...]
    //using keyPaths
    override public class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
        if key == "dateValue" {
            return Set(["visualDatePicker.dateValue"])
        }
        if key == "visualDatePicker.dateValue" {
            return Set(["dateValue"])
        }
        return Set([])
    }
}

class ViewController: NSViewController {
    @objc dynamic var objectControllerContent : ObjectControllerContent = ObjectControllerContent()

    @IBOutlet weak var label: NSTextField!
    @IBAction func btnClicked(_ sender: Any) {
        label.stringValue = "prop_dateTime is \(objectControllerContent.prop_dateTime)"
    }
}

class ObjectControllerContent : NSObject {
    @objc dynamic var prop_dateTime : Date?
}

结果:

github 项目:https://github.com/Florrr/VisualNSDatePicker

【问题讨论】:

  • 代码中self是哪个对象? Object Controller 是什么? prop_dateTime 是如何声明的?当您更改弹出框中的日期选择器时,文本日期选择器的视觉值如何更新?
  • prop_dateTime 必须用@objc dynamic 属性声明。顺便说一句,在keyPathsForValuesAffectingValue 版本中,您必须使用return super.keyPathsForValuesAffectingValue(forKey: key) 而不是Set[]
  • 我们如何在测试项目中重现该问题?
  • 请在您设置文本日期选择器值的位置添加代码。
  • 我仍然不明白“我尝试过的一些方法”的哪些陈述有效,哪些无效,我不熟悉reactive。设置objectValue 不会触发控件的绑定。见Make NSTextField update its bound value when setting its string value programmatically。

标签: swift macos cocoa datepicker key-value-observing


【解决方案1】:

设置dateValue 或objectValue 的NSDatePicker 或任何NSControl 不会触发绑定。绑定在sendAction(_:to:)中触发。

解决方案:

调用sendAction(_:to:),动作和/或目标可以是nil。

datePicker.dateValue = date
datePicker.sendAction(datePicker.action, to: datePicker.target)

或模仿绑定

datePicker.dateValue = date
guard
    let bindingInfo = datePicker.infoForBinding(NSBindingName.value),
    let observedObject = bindingInfo[NSBindingInfoKey.observedObject] as? NSObject,
    let observedKeyPath = bindingInfo[NSBindingInfoKey.observedKeyPath] as? String else {
        return
}
observedObject.setValue(self.dateValue, forKeyPath: observedKeyPath)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多