Подтвердить что ты не робот

Связывание 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". Это легко осуществить с помощью следующих привязок

bindings

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

textfieldbindings

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

initial display

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

Я думал, что это просто вопрос настройки привязки "Selected Object" на NSPopupButton

selected object

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

window2

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

4b9b3361

Ответ 1

Не используйте в этом случае "Selected Object". Свяжите всплывающее сообщение "Selected Index" с ключом контроллера NSArrayController selectionIndex. Пробовал это на вашем примере проекта, и он работает.

EDIT:

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

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

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

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

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

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