Обновление NSTokenField после программного изменения содержимого

Я реализовал NSTokenField, который использует некоторые настраиваемые объекты данных для отображения динамических данных. Делегат настроен нормально и отображает правильные значения токена.

Я также реализовал меню для токенов, которое позволяет выбрать формат, используемый для отображения каждого токена. Однако моя проблема в том, что я не могу заставить NSTokenField немедленно реагировать на эти изменения и перерисовывать токен в новом выбранном формате.

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

Итак, мой вопрос: есть ли способ просто запустить NSTokenField для перерисовки его содержимого без изменения фокуса и выбора?


person Claus Broch    schedule 29.02.2012    source источник


Ответы (2)


У меня была та же проблема, и я обнаружил, что единственное работоспособное решение - «сбрасывать» поле токена каждый раз, когда его содержимое изменяется. В основном это сводилось к запуску следующего метода контроллера представления, который обрабатывал представление с полем токена:

- (void) resetTokenField {

    // Force the token field to redraw itself by resetting the represented object.

    id anObject = [self representedObject];
    [self setRepresentedObject: nil];
    [self setRepresentedObject: anObject];
    [[self tokenField] setNeedsDisplay: YES];

}

Представленный объект - это объект, содержащий все отображаемые токены. В моем случае это был фрагмент богатого текста, где токены в основном являются тегами.

Я обнаружил, что NSTokenField был настоящей головной болью в шее, но продолжал настойчиво, поскольку мне очень нравилась его презентационная сторона.

РЕДАКТИРОВАТЬ: мое поле токена было привязано к методу tagsAsArray представленного объекта контроллера представления. Поэтому в основном я использовал привязки какао для решения проблемы.

person Roger    schedule 01.03.2012
comment
Спасибо, я рассмотрю ваши предложения позже сегодня. Полностью согласен с вашим Royal PITA;) - person Claus Broch; 01.03.2012
comment
Только что проверил ваше решение, и оказалось, что [tokenField setRepresentObject: nil]; имеет тот же побочный эффект, что и выключение и повторное включение ответа, а именно выбор всего поля токена. - person Claus Broch; 01.03.2012
comment
Нашел обходной путь, основанный на вашем решении: [tokenField setObjectValue: [NSArray arrayWithArray: [tokenField objectValue]]]; Кажется, что установка тех же значений, но внутри нового массива, вызывает перерисовку токена без побочного эффекта выбора. Это немного грязный прием, для которого Apple должна предоставить более чистое решение, но в любом случае я приму ваш ответ, поскольку он приведет меня к приемлемому решению. - person Claus Broch; 01.03.2012

Оказывается, вы должны вызывать setNeedsDisplay для объекта NSTextView, используемого NSTokenField, вместо вызова setNeedsDisplay для самого NSTokenField. Таким образом, работает следующий код: (Написано на PyObjC)

text_view = token_field.cell().fieldEditorForView_(token_field)
text_view.setNeedsDisplay_(YES)
person Li Chen Koh    schedule 04.04.2016