NSTextView textDidChange не вызывается через привязку - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть NSTextViews, где мне нужно отслеживать текущую конечную точку текста для размещения элементов интерфейса.

Я связываю строку модели с NSBindingName.value в текстовом представлении.

Когдатекст редактируется. Я обновляю расположение элементов интерфейса в

func textDidChange(_ notification: Notification)

... как делегат NSTextView.

Однако, если моя модель является источником обновления строкиэтот метод делегата никогда не вызывается, даже если текст корректно обновляется в NSTextView.

Итак, я делаю что-то не так, и связанное изменение должно вызвать textDidChange?

Если нет, то это ошибка или намеренно, должен ли я просто наблюдать и обновлять значения вручную и вызывать собственный метод делегата?Кажется, стыдно терять элегантность привязки.

Обратите внимание, что об этом уже спрашивали, но пометили как правильно ответили, когда это не так: NSTextView textDidChange / didChangeText не вызывается для привязок

1 Ответ

0 голосов
/ 08 февраля 2019

Метод didChangeText метода NSTextView не вызывается, когда привязка обновляет текст, а не текстовое представление, обновляющее модель.

didChangeText является источником объектаобязательное обновление.Если вы переопределите его и не вызовете super, привязка будет прервана.didChangeText вызывает метод делегата textDidChange.

К сожалению, didChangeText также вызывается довольно поздно в процессе обновления NSTextView - после вызовов делегата макета и хранилища.

Это огорчило меня, потому что мне нужна была модель дляизменить, прежде чем я вызвал мой делегат - я начал отдельные вычисления для высоты строки NSTableView с другим представлением.Если это было сделано до обновления модели, я получил неправильную высоту.

Я не нашел способа разграничить обновления модели и текста в строке из кода NSTextView.Я поймал все обновления строки в didProcessEditing в качестве делегата NSTextStorage.

func textStorage(_ textStorage: NSTextStorage,
                 didProcessEditing editedMask: NSTextStorageEditActions,
                 range editedRange: NSRange,
                 changeInLength delta: Int)
{
    if editedMask.contains(.editedCharacters) {
        textStringDidChange = true
    }
}

Я просто установил здесь флаг, потому что вызовы моего делегата здесь потерпели бы крах, если бы они попытались обновитьNSTextView никак.Затем я использовал этот флаг в следующем вызове NSLayoutManagerDelegate:

func layoutManagerDidInvalidateLayout(_ sender: NSLayoutManager)
    {
        if textStringDidChange {
            delegate?.textDidChange?(Notification(name: .init("")))
            textStringDidChange = false
        }
    }

didChangeText вызывается через некоторое время после этих вызовов делегатов.Поэтому мне приходилось обходиться инициализацией изменений в текстовом представлении, дважды вызывая моего делегата.Это неэффективно, но я не нашел способа отфильтровать это.

...