Как я могу постоянно получать выбранное значение ячейки из отфильтрованного NSTableView?

Контекст

У меня есть 2 столбца, основанный на ячейке NSTableView, управляемый NSArrayController.

  • Первый столбец заполнен флажками, чтобы указать, включено ли значение.
  • Второй столбец представляет имя элемента.

Представление связано с NSSearchField, поэтому фильтруется на основе предиката, который сравнивает строку поиска со строками в столбце 2.

Представление отображается правильно и фильтрует, как предполагалось, при изменении строки поиска.

Требование

Мне нужно разрешить пользователям включать не более 5 строк. Для этого я отслеживаю резервный массив на наличие изменений и отслеживаю количество включенных записей. Если количество превышает 5, я сообщаю пользователям предупреждение и отменяю выбор ранее включенной записи, получая выбранный индекс строки, а затем отключая этот индекс в резервном массиве. Я делаю это в блоке [willChange.. ..didChange] KVO.

Это работает, как предполагалось, когда представление не отсортировано, но, очевидно, вызывает проблемы, когда это так, потому что выбранная строка больше не соответствует соответствующему индексу в массиве.

Поэтому я использую следующий код, чтобы получить строковое значение выбранной ячейки, если представление отфильтровано (строка поиска не пуста). Затем я просматриваю массив и отключаю запись, соответствующую строке.

NSInteger selectedRow = [_tv_TableView selectedRow];
NSTableColumn* column=  [_tv_TableView tableColumns][1];
NSCell* cell = [column dataCellForRow:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

Эта проблема

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

Обновлять

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

i.e:

  1. Загрузить окно и выбрать 6 предметов
  2. Выбор 6-го элемента отменен, и пользователь предупрежден
  3. Применить фильтр
  4. Выберите новый 6-й элемент
  5. Выбор 6-го элемента отменен, и пользователь предупрежден
  6. Выберите другой 6-й элемент в том же фильтре
  7. Выбор 6-го элемента отменен, и пользователь предупрежден
  8. Введите новый фильтр
  9. Выберите новый 6-й элемент
  10. Выбор 6-го элемента отменен, и пользователь предупрежден
  11. Выберите новый 6-й элемент из того же фильтра
  12. Выбранный индекс правильный, но значение для выбранной строки совпадает с предыдущим выбором
  13. Пользователь неоднократно предупреждался, потому что правильная запись не отменяется, что приводит к 6 постоянно выбранным записям.

Однако по-прежнему бывают случаи, когда возвращается следующее значение строки, не являющееся ранее выбранным элементом.

Вопрос

Мои вопросы:

  1. Правильно ли я получаю выбранную строку для отфильтрованного списка?
  2. Как я могу постоянно получать строковое значение столбца 2 на основе выбранной строки, даже если список отсортирован?

Спасибо за уделенное время.

Решение

Я решил это, изменив код, который получает ячейку из:

NSInteger selectedRow = [_tv_TableView selectedRow];
NSTableColumn* column=  [_tv_TableView tableColumns][1];
NSCell* cell = [column dataCellForRow:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

To:

NSCell* cell = [_tv_TableView preparedCellAtColumn:1 row:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

person SeanTRobinson    schedule 30.07.2014    source источник


Ответы (2)


Простое решение состоит в том, чтобы связать привязку таблицы selectionIndexes к одноименному свойству контроллера массива. Затем вы можете получить доступ к -selectedObjects контроллера массива, чтобы найти выбранные объекты.

Когда у вас есть строка (или индекс) из таблицы, независимо от того, выбрана она или нет, вы можете использовать -arrangedObjects из NSArrayController. Это всегда будет соответствовать индексам.

Ячейки используются повторно. Нет ни одной ячейки, связанной с каждым местоположением (строка, столбец). С каждым столбцом связана ячейка, но она перенастраивается для каждой строки каждый раз, когда необходимо нарисовать строку или иным образом манипулировать ею. Вот почему вам нужна подготовленная ячейка. Тем не менее, ячейки концептуально находятся на уровне представления (в терминах Model-View-Controller). То, что вы делаете, должно быть в домене контроллера и модели, поэтому вам не следует обращаться к уровню представления (и в этом нет необходимости).

person Ken Thomases    schedule 30.07.2014

По какой-то причине внутреннее представление элементов не обновлялось при изменении фильтра в NSSearchField. Это возвращало значения, несовместимые с фактическим представлением.

Я решил это, изменив код, который получает ячейку из:

NSInteger selectedRow = [_tv_TableView selectedRow];
NSTableColumn* column= [_tv_TableView tableColumns][1];
NSCell* cell = [column dataCellForRow:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

To:

NSCell* cell = [_tv_TableView preparedCellAtColumn:1 row:row];
NSString* cellValue = (NSString*)[cell stringValue];
return cellValue;

До этого я также пытался принудительно обновить представление вручную, используя:

[_tv_TableView reloadData];

Но это никак не повлияло на результат. Мне все равно было бы интересно узнать, почему именно это происходит. Если я узнаю, я обновлю ответ.

person SeanTRobinson    schedule 30.07.2014