Реализация NSOutlineView для редактирования содержимого файла plist - PullRequest
1 голос
/ 22 октября 2010

Я пишу игру, используя cocos2d-iphone, и наши этапы определены в файлах .plist. Тем не менее, файлы становятся большими - поэтому я разработал редактор, который добавляет некоторую структуру процессу и разбивает большую часть списка на фиксированные поля. Однако для некоторых элементов все еще требуется функциональность типа редактора списков, поэтому я реализовал NSOutlineView на панелях, которые показывают «другие параметры». Я пытаюсь продублировать функциональность из редактора списков свойств XCode.

Я реализовал следующую систему; http://www.stupendous.net/archives/2009/01/11/nsoutlineview-example/

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

return [[parentObject allKeysForObject:item] objectAtIndex:0];

Однако, когда в данном словаре в дереве есть несколько элементов с одинаковым значением, этот оператор всегда возвращает первый элемент, имеющий это значение (кажется, что для сравнения строк используются значения isEqualToString: или hash). Это приводит к тому, что в ключевом столбце отображается «item1, item1, item1» вместо item1, item2, item3 (где все элементы 1-3 имеют значение «»). Затем я попробовал;

-(NSString*)keyFromDictionary:(NSDictionary*)dict forItem:(id)item
{
for( uint i = 0; i < [[dict allKeys] count]; i++ ) {
    id object = [dict objectForKey:[[dict allKeys] objectAtIndex:i]];

    if ( &object == &item ) {
        return [[dict allKeys] objectAtIndex:i];
    }
}   

return nil;
}

Но это всегда возвращает ноль . Я надеялся, что кто-то с немного большим опытом работы с NSOutlineView сможет предложить лучшее решение. Хотя эта проблема появляется только один раз в связанном примере, мне пришлось использовать ее несколько раз, например, при удалении элементов из словарей. Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

1 голос
/ 22 октября 2010
return [[parentObject allKeysForObject:item] objectAtIndex:0];

Однако, когда в данном словаре в дереве есть несколько элементов с одинаковым значением, этот оператор всегда возвращает первый элемент, имеющий это значение…

Хорошо, да уж.Вот что вы сказали ему: «Дайте мне все ключи для этого значения;достань мне первый элемент в массиве;вернуть это ».

… этот оператор всегда возвращает первый элемент, который имеет это значение (кажется, что для сравнения строк используются значения isEqualToString: или hash).

Этоне то утверждение, которое делает это;это то, как работают словари: каждый ключ может быть только в словаре один раз и может иметь только один объект в качестве значения, и это выполняется с использованием хэша ключа и путем отправки сообщений ключей isEqual: (не связанных с NSStringisEqualToString: - клавиши не обязательно должны быть строками *).

С другой стороны, значения не являются унифицированными.Любое количество ключей может иметь одинаковое значение.Вот почему переход от значений к ключам - и особенно к ключу a - так проблематичен.

* В любом случае, не в NSDictionary.Когда вы пытаетесь сгенерировать вывод plist, он прекратит работу, если в словаре есть какие-либо нестроковые ключи.

Я попытался в следующий раз;

-(NSString*)keyFromDictionary:(NSDictionary*)dict forItem:(id)item
{
    for( uint i = 0; i < [[dict allKeys] count]; i++ ) {
        id object = [dict objectForKey:[[dict allKeys] objectAtIndex:i]];

        if ( &object == &item ) {
            return [[dict allKeys] objectAtIndex:i];
        }
    }   

    return nil;
}

Но это всегда возвращает ноль.

Это наименьшая из проблем этого кода.

Во-первых, при итерации NSArray вы, как правило, не должны использовать индексы без крайней необходимости.Гораздо понятнее использовать быстрое перечисление .

Во-вторых, когда вам нужны индексы в NSArray, правильный тип - NSUInteger.Не смешивайте и не совмещайте типы, когда вы можете помочь.

В-третьих, я не знаю, что вы хотели сделать с оператором address-of, но на самом деле вы взяли адрес этих операторов.две переменные.Таким образом, вы сравнили, является ли локальная переменная object той же самой переменной, что и переменная аргумента item.Поскольку они не являются одной и той же переменной, этот тест всегда возвращает false, поэтому вы никогда не возвращаете объект - единственная другая точка выхода возвращает nil, так что это всегда происходит.

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

Вам нужно использовать что-то еще в качестве элементов.Использование ключей в качестве предметов было бы одним из способов;создание объекта модели для представления каждой строки было бы другим.

Если вы идете по маршруту модель-объект, не забудьте запретить нескольким строкам в одном виртуальном словаре иметь одинаковыеключ.NSMutableSet plus, реализующий hash и isEqual:, поможет в этом.

Вы, вероятно, также должны внести те же изменения в вашу обработку массивов.

0 голосов
/ 02 ноября 2010

Чтобы уточнить, я в конечном итоге решил эту проблему, создав прокси-объекты для каждой из коллекций в файле plist (то есть для каждого NSMutableArray или NSMutableDictionary). Это означало, что я по существу отразил структуру Plist и включил ссылки на исходные объекты на каждом уровне. Это позволило мне сохранить индекс массива для каждого объекта или ключа словаря, поэтому при сохранении элементов из представления структуры в структурах Plist я использовал свойства «ключ» или «индекс» в прокси-объекте.

...