Привязка NSArrayController к NSPopupButton и NSTextField

То, что я хочу достичь, кажется, должно быть довольно простым. Я разместил образец проекта здесь.

У меня есть NSArrayController, заполненный массивом NSDictionaries.

[[self controller] addObject:@{ @"name" : @"itemA", @"part" : @"partA" }];
[[self controller] addObject:@{ @"name" : @"itemB", @"part" : @"partB" }];
[[self controller] addObject:@{ @"name" : @"itemC", @"part" : @"partC" }];

Я заполняю NSPopupButton элементами этого массива на основе ключа name. Это легко сделать с помощью следующих привязок

привязки

Затем я хотел бы заполнить NSTextField текстом в ключе «часть» на основе текущего выбора NSPopupButton. Я установил следующую привязку:

textfieldbindings

Только с этими привязками в текстовом поле отображается «partC».

начальное отображение

Однако, если я изменю значение NSPopupMenu, то, что отображается в текстовом поле, не изменится.

Я думал, что это просто вопрос настройки привязки «Выбранный объект» к NSPopupButton.

выбранный объект

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

window2

Итак, что мне нужно сделать, чтобы это сработало?


person ericg    schedule 15.02.2013    source источник
comment
Как насчет установки пути ключа модели для вашей всплывающей кнопки?   -  person Jay    schedule 15.02.2013
comment
Для какой привязки? К чему? Установка ключевого пути модели для «выбранного объекта» на «часть» просто приводит к отображению «partC» в меню и возникновению исключения, когда я изменяю параметр меню.   -  person ericg    schedule 15.02.2013
comment
Следите за тем, что я написал в списке рассылки Cocoa Dev.   -  person uchuugaka    schedule 18.02.2013


Ответы (1)


Не используйте в этом случае «Выбранный объект». Привяжите привязку «Выбранный индекс» всплывающего окна к selectionIndex Ключу Контроллера NSArrayController. Попробовал на своем примере проекта, и он работает.

РЕДАКТИРОВАТЬ:

Вы спросили, почему уместно использовать selectionIndex вместо selectedObject. Сначала немного предыстории:

При привязке всплывающего меню есть три виртуальных «Коллекции», которые вы можете привязать: Контент - это абстрактный «список вещей, которые должны быть в меню» - вы всегда должны указывать Контент < / сильный>. Если вы не укажете ни Объекты содержания, ни Значения содержания, то набор значений, связанных с Контентом, будет использоваться в качестве «объектов» и строки, возвращаемые их -description методами, будут использоваться как «значения». Другими словами, Значения содержимого - это строки, отображаемые во всплывающем окне, а Объекты содержимого - это объекты, которым они соответствуют (которые, возможно, не являются строками и которые могут не иметь -description метода, подходящего для создания текста во всплывающем окне). Здесь важно понимать, что здесь потенциально задействованы три разных «виртуальных массива»: массив для содержимого, массив для объектов содержимого (которые могут быть разными). и массив для значений содержимого (которые также могут быть разными). Все они будут иметь одинаковое количество значений, и обычно объекты содержимого и значения содержимого будут функциями (в математическом смысле) соответствующих элементов в Content массив.

Следующее, что важно понять, - это то, что часть жизненной цели NSArrayController - отслеживать выбор пользователя. Это лишь слегка (если вообще) интересно в случае всплывающего окна, но начинает становиться гораздо более интересным в случае NSTableView. Внутренне NSArrayController отслеживает это, сохраняя NSIndexSet, содержащий индексы в массиве Content, которые выбираются в любой момент времени. Отсюда состояние выбора отображается несколькими различными способами для вашего удобства:

  • selectionIndexes, как описано - NSIndexSet, содержащий индексы выбранных элементов в массиве Content
  • selectionIndex - удобный вариант для приложений, не поддерживающих множественный выбор. Это можно рассматривать как эквивалент arrayController.selectionIndexes.firstIndex.
  • selectedObject также полезен в случаях единичного выбора и концептуально соответствует ContentObjectsArray[arrayController.selectionIndexes.firstIndex]
  • selection возвращает специальный объект (непрозрачный для потребителя), который брокеры считывают и записывают обратно в базовый объект (или объекты в случае множественного выбора) в массиве содержимого контроллера массива. Он существует, чтобы разрешить одновременное редактирование нескольких объектов в нескольких случаях выбора и обеспечить поддержку для других особых случаев. (Вы должны думать об этом свойстве как о доступном только для чтения; поскольку его тип непрозрачен для потребителя, вы никогда не сможете создать подходящее новое значение для записи в него. Имеет смысл делать такие вызовы, как: -[arrayController.selection setValue: myObject forKey: @"modelKey"], но это не < / em> имеет смысл совершать звонки типа -[arrayController setValue: myObject forKey: @"selection"]

С таким пониманием свойства selection давайте сделаем шаг назад и посмотрим, почему его не следует использовать в данном случае. NSPopUpButton пытается быть умным: вы предоставили ему список вещей, которые должны быть в меню, с помощью привязок Content и Content Values ​​. Затем вы дополнительно сказали ему, что хотите привязать его Выбранный объект к свойству NSArrayController selection. Вы, вероятно, думаете об этом как о привязке «только для записи», то есть «Уважаемое всплывающее окно, пожалуйста, возьмите выбор пользователя и вставьте его в arrayController», но привязка действительно двунаправленная. Поэтому, когда привязки обновляются, всплывающее окно сначала заполняет меню всеми элементами из привязок Content / Content Values ​​, а затем говорит: «О, вы говорите, что значение в arrayController.selection - это мое Выбранный объект. Это странно - его нет в списке вещей, связанных с моими привязками Content / Content Values ​​. Я лучше добавлю его в список для вас! Я сделаю это, вызвав -description на нем и вставив эту строку в меню за вас ". Но объект, который вы получаете из этой привязки Selected Object, является непрозрачным объектом выбора, описанным выше (и вы можете видеть из результата, что это класс _NSControllerObjectProxy, частный для AppKit класс, как намекает ведущее подчеркивание).

В общем, поэтому, почему привязка привязки выбранного объекта всплывающего окна к selection клавише контроллера массива - это неправильный поступок. К сожалению, как я уверен, вы уже обнаружили, что документация по привязкам какао только начинает касаться поверхности, так что не расстраивайтесь. Я работаю с привязками какао почти ежедневно в крупномасштабном проекте в течение нескольких лет, и я все еще чувствую, что есть много вариантов использования, которые я еще не полностью понимаю.

person ipmcc    schedule 18.02.2013
comment
Это то, что я написал в том же посте в списке разработчиков Cocoa. - person uchuugaka; 18.02.2013
comment
Если кто-то захочет дать более подробное объяснение, почему, мне было бы интересно. - person ericg; 19.02.2013
comment
@ericgorr Пытался объяснить еще кое-что; надеюсь, это имеет смысл. Это сложная тема. - person ipmcc; 19.02.2013