Использование экземпляров NSView в качестве ключей NSDictionary? - PullRequest
2 голосов
/ 06 декабря 2010

Я пытаюсь создать полусложный набор анимаций вида (представьте себе анимированную версию формы NSMatrix, в которой строки перемещаются по мере добавления или удаления других строк) и создания анимации. сделать маленький вспомогательный класс.

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

Для этого я использую экземпляр NSArray, чтобы отслеживать порядок (индексы) представлений, и я хотел бы использовать NSDictionary с представлениями в качестве ключей для отслеживания значения (сами значения находятся во вложенных словарях). То есть Я хотел бы иметь возможность сделать что-то это, например (псевдокод):

NSMutableDictionary* viewValuesDict = [NSDictionary dictionary];

// Loop thru an ordered NSArray
for( (NSView*) view in viewsArray ) {
    // Get some values we'll need later
    NSDictionary* associatedValues = [view getSomeValues];

    // ...and put them into viewValuesDict...
    [viewValuesDict setObject:associatedValues forKey:view];

    // and then things break because the NSView 'view'
    // doesn't support copyWithZone.... darn
}

Проблема в , я, конечно, не могу использовать NSView экземпляры в качестве ключей словаря, потому что ключи добавляются с использованием copyWithZone, который NSView не реализует.

Итак, как же получить уникальный ключ для экземпляра NSView? Я мог бы предположительно использовать [obj description], так как адрес памяти, который вы получаете, является идеальным UID, но, конечно, система должна работать с любым видом подкласса NSView, который может возвращать что-то еще полностью, так что это не хорошо.

Или мне лучше попробовать что-нибудь еще? Есть ли какая-нибудь альтернатива NSDictionary, где ключи просто не копируются? Потому что в этом случае мне действительно не нужно копировать ключи.

Ответы [ 4 ]

8 голосов
/ 06 декабря 2010

Иногда бывают случаи, когда вы хотите использовать представление (или NS, или UI) в качестве ключа в словаре. Я сталкивался с одной такой ситуацией. Я бы предпочел использовать objc_setAssociatedObject, но для этого требуется Snow Leopard. Бокс с NSValue будет работать, но если вам нужно много-много разыскивать при просмотре, постоянный бокс и распаковка указателей могут стать утомительными.

Существует два варианта создания словаря NSView => <object>.

  1. Использование NSMapTable
  2. Использование CFMutableDictionaryRef

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

CFMutableDictionaryRef - это базовый фонд, эквивалентный NSDictionary (они соединены по мосту бесплатно), но у него есть некоторые дополнительные параметры создания. Вы создаете один, используя CFDictionaryCreateMutable(), и для этого нужны два struct параметра. Одна - это структура, которая определяет поведение управления памятью (и другое) того, как обращаться с ключами словаря, а другая - это struct для определения поведения значений. Вы можете создать CFMutableDictionaryRef с опциями сохранения ключей (вместо их копирования) и последующего сохранения значений. Как только вы это сделаете, вы можете привести CFMutableDictionaryRef к NSMutableDictionary и использовать его так, как вы ожидаете, просто чтобы ключи были сохранены, а не скопированы.

2 голосов
/ 06 декабря 2010

Используйте NSMapTable вместо NSDictionary (конечно, вы должны быть уверены, что тщательно управляете временем жизни вашего объекта, если вы не используете сборщик мусора). Эта статья содержит краткое описание того, как ее использовать.

1 голос
/ 06 декабря 2010

Как сказал andyvn22, реорганизуйтесь!Но если это нецелесообразно:

  • Если вы нацеливаетесь на Snow Leopard, и ассоциации, скорее всего, сохранятся в течение срока действия представлений, используйте objc_setAssociatedObject().
  • В противном случае используйте [NSValue valueWithNonretainedObject:] вместо -description.(Как говорится, он не сохраняет объект, но ваш массив сохраняет.)
0 голосов
/ 06 декабря 2010

Создайте свои словари так, чтобы одним из их значений было представление;затем переставьте код так, чтобы вам не нужно было искать словарь на основе представления, а вместо этого начинать либо со словарей, либо с индекса (помещение словарей в массив), либо с уникального идентификатора вашего собственного создания (помещение словарей всловарь; идентификатор может быть простым порядковым номером для каждого нового представления, которое вы начинаете отслеживать).Если вы не делаете что-то очень сложное и динамичное, не должно быть необходимости искать информацию, предоставляя только NSView.

...