iOS UITableView: настраиваемые разделы, использующие информацию из объекта JSON, а не просто ее подсчет

Скажем, у меня есть этот JSON:

[
    {"x":"01", "ID":"1"},
    {"x":"02", "ID":"2"},
    {"x":"02", "ID":"3"},
    {"x":"03", "ID":"4"},
    {"x":"03", "ID":"5"},
    {"x":"03", "ID":"6"},
    {"x":"03", "ID":"7"}
]

и я хочу создать UITableView следующим образом:

------------
Section 01
------------
ID: 1
------------
Section 02
------------
ID: 2
ID: 3
------------
Section 03
------------
ID: 4
ID: 5
ID: 6
ID: 7

Как узнать, сколько разделов мне нужно и как вывести правильные данные в каждом разделе?


person John Doe    schedule 18.12.2012    source источник
comment
Можете ли вы вообще изменить формат JSON?   -  person Shaun    schedule 19.12.2012
comment
Нет... Это сломало бы много других вещей.   -  person John Doe    schedule 19.12.2012
comment
Вы получаете этот JSON из веб-сервиса, которым управляете, или он связан с вашим приложением? Могли бы вы изменить его, если бы захотели? Единственная причина, по которой я спрашиваю, заключается в том, что вам придется написать код на своем клиенте, чтобы преобразовать его в нужный формат. Где, как если бы вы могли создать хороший JSON, это просто облегчило бы вашу жизнь.   -  person Shaun    schedule 19.12.2012
comment
Я определенно вижу вашу точку зрения здесь. Я мог бы изменить его, да, но так как это сломало бы много других вещей, я согласен с тем, что мой клиент анализирует его в формате, который я могу использовать. В любом случае это хорошее упражнение :)   -  person John Doe    schedule 19.12.2012


Ответы (3)


Первое, что нужно сделать, это преобразовать этот JSON в структуру данных Objective-C. Я рекомендую массив массивов, где "X" является индексом каждого массива значений "ID".

Что-то типа:

NSMutableArray *tableSections;
NSMutableArray *sectionData;

CustomDataObject *yourCustomDataObject;

int sectionIndex;

//Pseudo-code to create data structure
for(data in json) {

    sectionIndex = data.X;

    yourCustomDataObject = [[CustomDataObject alloc] initWithId:data.ID];

    //Do index check first to insure no out of bounds
    if(sectionIndex != OutOfBounds)
        sectionData = [tableSections objectAtIndex:sectionIndex];

    //Create the new section array if there isn't one for the current section
    if(!sectionData) {
        sectionData = [NSMutableArray new];
        [tableSections insertObject: sectionData atIndex: sectionIndex];
        [sectionData release];
    }

    [sectionData addObject: yourCustomDataObject];
    [yourCustomDataObject release];
}

Приведенный выше код — это всего лишь псевдокод, который поможет вам начать работу. Создание этого массива массивов, вероятно, вы уже делали раньше.

Важной частью является доступ к этим данным путем реализации протокола UITableViewDataSource. Я рекомендую создать подкласс UITableView и реализовать протокол UITableViewDataSource в вашем собственном подклассе.

Вам понадобятся эти методы:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [tableSections count];
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[tableSections objectAtIndex: section] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    //Implement as you normally would using the data structure you created

    NSMutableArray *sectionData = [tableSections objectAtIndex: indexPath.section];
    CustomDataObject *dataObject = [sectionData objectAtIndex: indexPath.row];

    NSLog(@"\n**** Debug Me *****indexPath: section: %i row: %i \ndataObject%@", indexPath.section, indexPath.row, dataObject);
}

Этого должно быть достаточно, чтобы вы начали. Выяснение остальных деталей должно быть хорошей практикой.

person Brandon Brodjeski    schedule 19.12.2012
comment
Так что в основном я должен закончить с: [ {"01": {"ID":"1"} } {"02": {"ID":"2"}, {"ID":"3"} } {"03": {"ID":"4"}, {"ID":"5"}, {"ID":"6"}, {"ID":"7"} } ] и затем использовать это? - person John Doe; 19.12.2012
comment
Фигурные скобки сбивают с толку при представлении структуры target-c... Может быть больше похоже на: [[1], [2,3], [4, 5, 6, 7]] - person Brandon Brodjeski; 19.12.2012
comment
Чтобы более внимательно следить за вашими обозначениями... [ [{"ID":"1"}], [{"ID":"2"},{"ID":"3"}], [{"ID":"4"}, {"ID":"5"}, {"ID":"6"}, {"ID":"7"}] ]. Квадратные скобки обозначают массив. Фигурные скобки обозначают пользовательский объект данных. - person Brandon Brodjeski; 19.12.2012
comment
Я собирался использовать массив, содержащий несколько массивов, каждый из которых идентифицируется ключом (разделом) и содержит данные для каждого раздела. Я думаю, мы понимаем друг друга. Ваш, вероятно, лучше, поскольку вы не определяете его конкретно, а разделы начинаются с 0. Я буду держать вас в курсе, как это работает! - person John Doe; 19.12.2012
comment
Извини, @Брэндон, но я не могу понять это. Я пытался использовать ваш псевдокод всеми возможными способами, но tableSections всегда будет пустым. Проверьте эту вставку pastebin.com/AWBbFdLQ. - person John Doe; 20.12.2012

Если предположить, что значения «x» будут увеличиваться с 1 до n без пропуска каких-либо значений, то количество необходимых вам разделов будет просто последним значением «x» (т. е. n).

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

person username tbd    schedule 18.12.2012

Закончил с этим решением:

    NSMutableDictionary *result = [NSMutableDictionary dictionary];
    for(NSDictionary* dict in data) {
        NSNumber *x = [dict objectForKey:@"x"];
        NSMutableArray *resultsForX = [result objectForKey:x];

        if(!resultsForX) {
            resultsForX = [NSMutableArray array];
            [result setObject:resultsForX forKey:x];
        }

        [resultsForX addObject:dict];
    }

    NSMutableArray *newArr = [result allValues];
person John Doe    schedule 20.12.2012