Создать список свойств словаря программно - PullRequest
10 голосов
/ 14 июля 2009

Я хочу программно создать словарь, который будет подавать данные в мой UITableView, но мне трудно с этим. Я хочу создать словарь, который будет напоминать этот список свойств (изображение) дать или взять пару элементов.

Я посмотрел на «Руководство по программированию списков свойств: создание списков свойств программным способом» , и я создал свой небольшой пример:

//keys

NSArray *Childs = [NSArray arrayWithObjects:@"testerbet", nil];
NSArray *Children = [NSArray arrayWithObjects:@"Children", nil];
NSArray *Keys = [NSArray arrayWithObjects:@"Rows", nil];
NSArray *Title = [NSArray arrayWithObjects:@"Title", nil];

//strings

NSString *Titles = @"mmm training";

//dictionary 

NSDictionary *item1 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
NSDictionary *item2 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
NSDictionary *item3 = [NSDictionary dictionaryWithObject:Childs, Titles forKey:Children , Title];
NSArray *Rows = [NSArray arrayWithObjects: item1, item2, item3, nil];
NSDictionary *Root = [NSDictionary dictionaryWithObject:Rows forKey:Keys];

// NSDictionary *tempDict = [[NSDictionary alloc] //initWithContentsOfFile:DataPath];
NSDictionary *tempDict = [[NSDictionary alloc] initWithDictionary: Root];

Я пытаюсь использовать эти данные иерархии для моих табличных представлений.

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

Я все еще новичок в разработке для iPhone, так что терпите меня. ;)

Ответы [ 4 ]

24 голосов
/ 14 июля 2009

Это ситуация, когда «научить человека ловить рыбу» - гораздо более полезный подход, чем «дать человеку рыбу». Как только вы поймете основные принципы и API NSDictionary, вам станет намного легче создать собственное решение. Вот несколько наблюдений и пунктов обучения:

  • Метод +dictionaryWithObject:forKey: используется для создания NSDictionary с одной парой ключ-значение. Он не будет принимать разделенные запятыми аргументы после каждого двоеточия (:) в вызове метода, только один. Чтобы создать словарь с несколькими парами ключ-значение, используйте один из 2 связанных методов: +dictionaryWithObjects:forKeys:, который принимает два объекта NSArray, содержащих значения и ключи, или +dictionaryWithObjectsAndKeys:, который чередуется ( объект, ключ, объект, ключ) с завершающим аргументом nil.
  • Упростите код создания. Вам не нужен миллион локальных переменных, просто чтобы создать вещь. Используйте встроенные аргументы там, где это имеет смысл. Один из способов сделать это - создать словарь в коде как NSMutableDictionary , а затем (при необходимости) сделать его неизменную копию, вызвав для него -copy. (Помните, что метод copy возвращает новый объект, который вы должны освободить, чтобы избежать утечек памяти.) Таким образом, вам не нужно иметь переменную для каждого отдельного значения, чтобы вы могли создать структуру "один раз" ) на каждом уровне.
  • Используйте +arrayWithObject: для создания NSArray с одним объектом.
  • (Рекомендации по стилю) Никогда не используйте заглавную букву, чтобы начать имя переменной, метода или функции. (Обратите внимание, что SO выделяет переменные начальных заглавных букв, такие как имена классов.) Это, безусловно, поможет тем, кто читает ваш код, запутаться в ваших намерениях из-за схемы именования.

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

NSDictionary *item1 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"Screen J",[NSNumber numberWithInt:3],nil]
                                                  forKeys:[NSArray arrayWithObjects:@"Title",@"View",nil]];
NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
                                        @"Screen I", @"Title", 
                                        [NSArray arrayWithObject:item1], @"Children", 
                                        nil];
...
2 голосов
/ 15 июля 2009

Я не уверен, что понимаю основную цель здесь.

Кажется, что во время выполнения вы создаете глубокий словарь со многими дочерними узлами. Но вы создаете все это с помощью статического кода ... почему вы не можете просто создать plist (например, тот, на котором у вас было изображение) и прочитать его в NSDictionary? И NSDictionary, и NSArray имеют методы, которые позволяют просто читать в файле и получать весь заполненный объект. Тогда это гораздо проще редактировать и понимать. Этот метод dictionaryWithContentsOfFile.

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

Наконец, мне лично не нравится метод dictionaryWithObjects:forKeys: в NSDictionary для построения словаря. Если вам нужно так поступить, я бы предпочел альтернативный метод dictionaryWithObjectsAndKeys:, который делает то же самое, но сохраняет ключи с объектами:

NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
                       @"Screen J",
                       @"Title",
                       [NSNumber numberWithInt:3],
                       @"View"];
0 голосов
/ 15 июля 2009

сначала .. супер! спасибо .. я действительно ценю объяснение и фрагмент кода. Поскольку вы дали мне такое хорошее объяснение, надеюсь, вы не против, чтобы я задал еще пару вопросов.

Сначала я сделал, как вы предложили, и вот что я придумал: (На этот раз я использовал свой исходный список свойств вместо примера, так что именно здесь таблица детализации получает его (или нуждается в его) триэструктуру).

http://img509.imageshack.us/img509/7523/picture2lsg.png

NSDictionary *root = [NSMutableDictionary dictionary];
NSDictionary *item1 = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:@"VirtuaGym Online"] forKey:[NSArray arrayWithObjects:@"Title"]];
NSDictionary *item2 = [NSDictionary dictionaryWithObject:[NSArray arrayWithObject:@"Do the training"] forKey:[NSArray arrayWithObjects:@"Title"]];
NSDictionary *item3 = ... 

[root setObject:item1 forKey:@"Item 1"];
[root setObject:item2 forKey:@"Item 2"];

Также провел какое-то исследование и попробовал что-то еще с другим вводом ..

NSMutableArray *Rows = [NSMutableArray arrayWithCapacity: 1];

for (int i = 0; i < 4; ++i) {
  NSMutableArray *theChildren = [NSMutableArray arrayWithCapacity: 1];
  [theChildren addObject: [NSString stringWithFormat: @"tester %d", i]];
NSString *aTitle = [NSString stringWithFormat: @"Item %d", i];
  NSDictionary *anItem = [NSDictionary dictionaryWithObjectsAndKeys: aTitle, @"Title", theChildren, @"Children"];
  [Rows addObject: anItem];
}

NSDictionary *Root = [NSDictionary withObject: Rows andKey: @"Rows"];

Я решил просто протестировать оба из них, но это делает то, что я хочу. Это дает мне ошибку EXC_BAD_ACCESS.

Мне также было интересно, так как я видел, как вы используете число в своем фрагменте кода, не могли бы вы также использовать NSString, так как это то, что использует plist ... может быть, конечно, здесь

NSDictionary *item1 = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"Screen J",[NSNumber numberWithInt:3],nil]
                                                  forKeys:[NSArray arrayWithObjects:@"Title",@"View",nil]];

и в-третьих, вопрос о моем возможном подходе к моему приложению. У меня есть XML-парсер, который сохраняет определенную информацию в разных массивах. Я хочу использовать эту информацию для моих развернутых UITableviews (infoFirstScreen [] infoSecondScreen [] infoThirdScreen []). Предоставленная информация должна быть связана как дерево, которое я показал вам выше. По этой причине я хотел построить словарь в коде, чтобы я мог взять информацию из моих массивов и вставить ее сюда. Мой вопрос, как вы думаете, мой подход правильный, неправильный или есть более быстрый путь?

снова очень ценю объяснение;)

0 голосов
/ 14 июля 2009
NSMutableDictionary *topLevel = [NSMutableDictionary dictionary];

NSMutableDictionary *item1 = [NSMutableDictionary dictionary];
NSString *item1title = [NSString stringWithString:@"Title 1"];
NSMutableDictionary *item1children = [NSMutableDictionary dictionary];

//  create children
NSString *item1child1 = [NSString stringWithString:@"item 1, child 1"];

NSMutableDictionary *item1child2 = [NSMutableDictionary dictionary];
NSString *item1child2title = [NSString stringWithString:@"Title 1-2"];
NSMutableDictionary *item1child2children = [NSMutableDictionary dictionary];

NSString *item1child2child1 = [NSString stringWithString:@"item 1, child 2, child 1"];
NSString *item1child2child2 = [NSString stringWithString:@"item 1, child 2, child 2"];

[item1child2 setObject:item1child2title forKey:@"Title"];
[item1child2children setObject:item1child2child1 forKey:@"item 1 child2 child 1"];
[item1child2children setObject:item1child2child2 forKey:@"item 1 child2 child 2"];

[item1child2 setObject:item1child2children forKey:@"children"];

//  add children to dictionary
[item1children setObject:item1child1 forKey:@"item1 child1"];
[item1children setObject:item1child2 forKey:@"item1 child2"];

//  add to item 1 dict
[item1 setObject:item1title forKey:@"Title"];
[item1 setObject:item1children forKey:@"children"];

NSMutableDictionary *item2 = [NSMutableDictionary dictionary];
NSString *item2title        = [NSString stringWithString:@"Title"];
NSMutableDictionary *item2children  = [NSMutableDictionary dictionary]; 

NSString *item2child1 = [NSString stringWithString:@"item 2, child 1"];
NSString *item2child2 = [NSString stringWithString:@"item 2, child 2"];
NSString *item2child3 = [NSString stringWithString:@"item 2, child 3"];

//  add children to dictionary
[item2children setObject:item2child1 forKey:@"item2 child1"];
[item2children setObject:item2child2 forKey:@"item2 child2"];
[item2children setObject:item2child3 forKey:@"item2 child3"];

//  add to item 2 dict
[item2 setObject:item2title forKey:@"Title"];
[item2 setObject:item2children forKey:@"children"];

[topLevel setObject:item1 forKey:@"Item 1"];
[topLevel setObject:item2 forKey:@"Item 2"];
...