Обвязка Swift KVO не обновлена - PullRequest
0 голосов
/ 06 января 2019

В моем приложении macOS я хочу объединить текстовое с визуальным NSDatePicker. Поэтому я создал собственный NSDatePicker, который показывает всплывающее окно при нажатии.

Textual and Visual NSDatePicker

Текстовое средство выбора связано с переменной с помощью инспектора привязок: binding inspector of textual picker

Моя проблема заключается в том, что, хотя текстовое средство выбора обновляется визуально при выборе чего-либо в всплывающем окне, значение привязки (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?
}

Результат: Result

GitHub проекта: https://github.com/Florrr/VisualNSDatePicker

1 Ответ

0 голосов
/ 18 января 2019

Установка 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)
...