Создать список свойств словаря программным путем

Я хочу программно создать словарь, который передает данные в 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, так что несите меня.;)

Ответ 1

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

  • Метод +dictionaryWithObject:forKey: используется для создания NSDictionary с одной парой ключ-значение. Он не будет принимать аргументы, разделенные запятыми, после каждого двоеточия (:) в вызове метода, только один. Чтобы создать словарь с несколькими парами ключ-значение, используйте один из двух связанных методов: +dictionaryWithObjects:forKeys:, который принимает два объекта NSArray, содержащие значения и ключи, или +dictionaryWithObjectsAndKeys:, который чередует (объект, ключ, объект, ключ) с завершающим аргументом nil.
  • Упростите код создания. Для создания вещи вам не требуется миллион локальных переменных. Используйте встроенные аргументы, где это имеет смысл. Один из способов сделать это - создать словарь в коде как NSMutableDictionary, затем (при необходимости) сделать неизменяемую копию его называя -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

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

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

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

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

NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
                       @"Screen J",
                       @"Title",
                       [NSNumber numberWithInt:3],
                       @"View"];

Ответ 3

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"];

Ответ 4

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

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

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 []). Предоставленная информация должна быть подключена как дерево, которое я показал вам выше. Именно по этой причине я хотел построить словарь в коде, чтобы я мог получать информацию из своих массивов и вставлять ее здесь. Как вы думаете, мой вопрос правильный, неправильный или есть более быстрый способ?

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