Swift KVO 绑定未更新
Swift KVO binding not updated
在我的 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([=11=], forKey: "dateValue")})
_ = visualDatePicker.reactive.objectValue.observeNext(with: {sender.setValue([=11=], forKey: "dateValue")})
//using willChange
_ = self.reactive.objectValue.observeNext(with: {visualDatePicker.willChangeValue(forKey: "dateValue"); visualDatePicker.dateValue = [=11=] as! Date; visualDatePicker.didChangeValue(forKey: "dateValue")})
_ = visualDatePicker.reactive.objectValue.observeNext(with: {self.willChangeValue(forKey: "dateValue"); self.dateValue = [=11=] 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?
}
结果:
设置 dateValue
或 objectValue
或 NSDatePicker
或任何 NSControl
不会触发绑定。绑定在 sendAction(_:to:)
.
中触发
解决方案:
调用sendAction(_:to:)
,动作and/or目标可以是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)
在我的 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([=11=], forKey: "dateValue")})
_ = visualDatePicker.reactive.objectValue.observeNext(with: {sender.setValue([=11=], forKey: "dateValue")})
//using willChange
_ = self.reactive.objectValue.observeNext(with: {visualDatePicker.willChangeValue(forKey: "dateValue"); visualDatePicker.dateValue = [=11=] as! Date; visualDatePicker.didChangeValue(forKey: "dateValue")})
_ = visualDatePicker.reactive.objectValue.observeNext(with: {self.willChangeValue(forKey: "dateValue"); self.dateValue = [=11=] 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?
}
结果:
设置 dateValue
或 objectValue
或 NSDatePicker
或任何 NSControl
不会触发绑定。绑定在 sendAction(_:to:)
.
解决方案:
调用sendAction(_:to:)
,动作and/or目标可以是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)