Рассмотрим первый столбец. Он связан с контроллером товара, arrangedObjects
, name
. Получает ли каждая ячейка массив имен? Нет, каждый получает одно имя.
Хотя эта колонка связывание иногда выражается как ключевой путь, такой как Item Controller.arrangedObjects.name
, способ, которым он фактически работает, состоит в том, что столбец в целом показывает arrangedObjects
, по одному элементу на строку, но name
применяется к каждому элементу этого набора отдельно. Поэтому каждая ячейка имеет одно имя.
Теперь рассмотрим ваш новый столбец. Строки снова соответствуют arrangedObjects
Контроллер элемента, но путь ключа модели применяется к каждому элементу индивидуально. Но путь ключа модели содержит оператор коллекции @sum
, который не подходит для отдельного элемента (объект Item
). Отсюда и ошибка.
Вы можете создать текстовое поле (вне таблицы), которое отображает сумму цены всех элементов выбранного хранилища. Вы привязывали бы привязку значения текстового поля к контроллеру товара, arrangedObjects
, @sum.price
. Текстовое поле работает иначе, чем столбец таблицы, так как у него есть одна вещь для отображения. Он действительно использует результат [ItemController valueForKeyPath:@"[email protected]"]
. Оператор коллекции будет применен к коллекции.
Вы также можете связать текстовое поле Item Controller, selection
, @sum.price
, чтобы она выводила сумму цен пунктов выбранных в таблице элементов.
Привязки не предоставляют никакой возможности получить текущую сумму, если я понимаю, что вы подразумеваете под этим (первая строка показывает цену первого элемента, вторая строка показывает сумму цен первого и второго пунктов , и т.д.). Такая текущая сумма будет зависящей от контекста. Значение данной строки будет зависеть от значений предыдущих строк. Например, сортировка таблицы по-разному означала бы, что текущая сумма рядом с данным элементом изменится, поскольку набор элементов перед изменением. Привязки не могут этого сделать. Они не знают о позиции, указателе или братьях и сестрах.
Update:
Чтобы получить выполняющийся сумму, вам нужно не использовать привязки для столбца. Сделайте свой просмотр или оконный контроллер принятым NSTableViewDataSource
, если он этого еще не сделал. Затем подключите выход dataSource
к виду на столе.
В вашем классе источника данных реализуйте -tableView:objectValueForTableColumn:row:
. Проверьте столбец identifier
. Для любых столбцов, отличных от столбца текущей суммы, возвращайте nil
, чтобы он использовал значение из привязок столбцов.
Для бегущей колонки суммы, прямолинейная, но неэффективная реализация будет что-то вроде:
NSRange range = NSMakeRange(0, rowIndex + 1);
NSArray* rowsToSum = [self.itemController.arrangedObjects subarrayWithRange:range];
return [rowsToSum valueForKeyPath:@"@sum.price"];
Вы также должен были бы способом сообщить виду таблицы, когда ячейки в столбце Запущенных сумм должны быть перезагружается (пересчитывается). Вы должны использовать наблюдение за ключевыми значениями для наблюдения за self
для изменения пути ключа @"itemController.arrangedObjects.price"
. Вы должны установить это в -viewDidLoad
или -windowDidLoad
. Не забывайте оторвать его, когда контроллер сделан.
Когда уведомление об изменении отправлено - т. Е.когда вызывается -observeValueForKeyPath:ofObject:change:context:
- вы должны вызвать -reloadDataForRowIndexes:columnIndexes:
в представлении таблицы, чтобы указать, что все индексы строк в столбце текущей суммы должны быть перезагружены.
Это должно работать, но оно будет ужасно неэффективным, как только вы получите значительное количество строк.
Таким образом, чтобы оптимизировать, вы должны кэшировать текущие суммы, но вам нужно быть осторожным, чтобы сделать недействительным кеш.
В основном, имеют переменную экземпляра, такую как _cacheIsValid
. Как и все переменные экземпляра, он будет начинать с нуля (false) по умолчанию. В поле -tableView:objectValueForTableColumn:row:
вы можете проверить, действительно ли оно. Если это не так, вы должны построить его и записать, что он действителен. Затем, или если он уже был действительным, просто верните элемент для запрошенной строки.
Чтобы создать кеш, перейдите по ссылке self.itemController.arrangedObjects
, вычисляя текущую сумму при прохождении и добавляя каждое значение в конец массива. Вы можете использовать массив примитивов типа C или NSMutableArray
NSNumber
s, как вы предпочитаете. (Управление памяти для массивов C-стиля можно сделать проще с помощью NSMutableData
для буфера.)
Вы исправите кэш в -observeValueForKeyPath:...
, прежде чем говорить виду таблицы, чтобы перезагрузить бегущее столбец суммы.
Для следующего шага в эффективности вы можете перепрограммировать кэш в это время и сравнить значения с существующим кешем (если он действителен) по мере того, как вы идете. Накопите в NSMutableIndexSet
индексы строк только тех строк, для которых фактически была изменена кэшированная текущая сумма, и используйте это при вызове -reloadDataForRowIndexes:columnIndexes:
. Таким образом, представление таблицы только перезагружает ячейки, которые фактически изменились.
Вы должны быть четкими и конкретными в отношении привязок. Например, «Контроллер элемента« NSArrayController »имеет привязку к содержимому, привязанную к контроллеру хранилища« NSArrayController », к ключу контроллера« выбор »,« путь к элементу ключа модели ». Связывание содержимого нового столбца связано с элементом Controller, ключ контроллера? ??, путь ключа модели '@ sum.price'." Или что на самом деле имеет место. Какие привязки объектов привязаны к чему, с помощью какого ключа контроллера и какого пути ключа ключа? Кроме того, вы оставили информацию об ошибке, например, какой класс не соответствует KVC. –
@KenThomases Спасибо, см. Редактирование. – littleDrummerBoy