Как заполнить текстовые метки ячейки прототипа с помощью объекта NSDictionary, заполненного данными JSON, с помощью AFNetworking

Новинка для iOS. Я загружаю данные JSON с помощью AFNetworking и помещаю данные в объект Dictionary. Это делается в следующем коде:

-(void)locationRequest
{
NSURL *url = [NSURL URLWithString:@"http://sitespec/php/getlocations.php"];

NSURLRequest *request = [NSURLRequest requestWithURL:url];
//AFNetworking asynchronous url request
AFJSONRequestOperation *operation = [AFJSONRequestOperation
                                     JSONRequestOperationWithRequest:request
                                     success:^(NSURLRequest *request, NSHTTPURLResponse         *response, id responseObject)
                                     {

                                         self.locationsFromJSON = (NSDictionary *)responseObject;

                                         NSLog(@"JSON RESULT %@", responseObject);
                                         NSLog(@"JSON DICTIONARY %@", _locationsFromJSON);
                                         [self.tableView reloadData];
                                     }
                                     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id responseObject)
                                     {
                                         NSLog(@"Request Failed: %@, %@", error, error.userInfo);
                                     }];

[operation start];

}

Я получаю данные и заполняю массив Dictionary, как видно из результатов вызовов NSLOG ниже:

2013-05-12 12:44:08.851 sitespec[2024:c07] JSON RESULT (
    {
    city = "Rocky Mount";
    id = 1;
    name = "Rocky Mount";
    phone = "(252) 451-1811";
    state = NC;
    "street_address" = "620 Health Drive";
    zip = 27804;
},
    {
    city = "Elizabeth City";
    id = 2;
    name = "Elizabeth City";
    phone = "(252) 335-4355";
    state = NC;
    "street_address" = "109 Corporate Drive";
    zip = 27906;
}
)
2013-05-12 12:44:08.852 sitespec[2024:c07] JSON DICTIONARY (
    {
    city = "Rocky Mount";
    id = 1;
    name = "Rocky Mount";
    phone = "(252) 451-1811";
    state = NC;
    "street_address" = "620 Health Drive";
    zip = 27804;
},
    {
    city = "Elizabeth City";
    id = 2;
    name = "Elizabeth City";
    phone = "(252) 335-4355";
    state = NC;
    "street_address" = "109 Corporate Drive";
    zip = 27906;
}
)

НО, вот где я потерял.....

Как мне получить доступ к этим данным в объекте Dictionary в моем

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

метод?

Что-то типа:

 static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

cell.textLabel.text = [self.locationsFromJSON objectForKey:@"name"]; 

???

Это не работает, и я получаю ошибку SIGBART. Я просто не могу понять, как считывать данные и заполнять табличное представление?

Как мне это сделать? ЛЮБАЯ помощь ОЧЕНЬ приветствуется.....


person Tommy Alexander    schedule 12.05.2013    source источник


Ответы (3)


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

Итак, Tommy, я настоятельно рекомендую вам создать модель класса с именем Address (например) и добавить все атрибуты JSON в качестве свойств в класс вашей модели. Когда вы анализируете JSON, вы создаете экземпляры класса Address, которые вы будете добавить в массив. После этого в вашем классе табличного представления у вас будет массив адресов и для:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section ты вернешься yourAddressesArray.count

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {    Address *address = [yourAddressesArray objectAtIndex:indexPath.row];    //assign your address properties to labels etc 

}

Это проще, когда у вас есть модельные классы;)

ИЗМЕНИТЬ ДЛЯ АНАЛИЗА

Из того, что я вижу в вашем вопросе, у вас есть множество словарей. Поэтому я предлагаю сделать что-то вроде этого:

В вашем классе Address создайте метод imit с помощью josn:

-(id)initAddressWithJSON:(id)JSON {
    slef = [super init];
    if(self) {
      self.city = [JSON objectForKey:@"city"];
      // set all the properties here
    }
    return self;
}

Когда вы получили вызванный ответ json, скажем, «jsonResopnse», вы должны сделать что-то вроде:

-(NSArray*)myAddressesFromJSON:(id)JSON {

   //you should add a validation here for JSON  (not null not empty)
   NSMutableArray *addresses = [[NSMutableArray alloc] init];
   Address *address;
   for(NSDictionary *addressDict in JSON) {
       address = [[Address alloc] initWithJSON:addressDict];
       [addresses addObject:address]; 
   }
   return addresses;
}

Обратите внимание, я написал код из головы и не использовал Xcode :) и возможно, что есть некоторые ошибки сборки (орфографические ошибки), но я надеюсь, что вы поняли идею. Также я полагаю, что вы используете JSONKit.

person danypata    schedule 12.05.2013
comment
Я создал модель Address и добавил все атрибуты своих данных JSON. Я импортировал файл Address.h в свой файл tableView.m, откуда загружаю данные и хочу показать tableView. У меня есть определенный массив с именем locationFromJSON, чтобы делать то, что вы указали выше. Тем не менее, продолжая вопрос, вы говорите, что когда вы анализируете свой JSON, вы создаете экземпляры класса Address, которые вы добавите в массив. У меня есть ответ JSON в возвращаемом значении: responseObject. Как создать экземпляры класса Address и добавить их в массив? - person Tommy Alexander; 12.05.2013

Как я вижу, вы используете запрос JSON и UITableView в одном классе. Установите точку останова в методе cellForRowAtIndexPath и проверьте, что если данные уже есть. если нет, то:

спросите в методе - (NSInteger)numberOfRowsInSection:(NSInteger)section или уже в numberOfSections если ваш словарь уже заполнен. иначе вернуть 0.

И в методе, где вы получаете данные JSON, вызовите [tableView reloadData];

если это не проблема, скажите, пожалуйста, где вы получаете ошибку SIGBART;)

person geo    schedule 12.05.2013

Спасибо danypata за отличный отзыв. Я пошел немного другим путем, чтобы добиться этого. Что заставило меня задуматься, так это комментарий danypata «похоже, у вас есть массив словарей в вашем ответе JSON»... В блоке AFNetworking, где я получаю ответ JSON, я назначаю объект JSON массиву, определенному как свойство в текущий TableViewCONtroller.

-(void)locationRequest

{ NSURL *url = [NSURL URLWithString:@"myurl"];

NSURLRequest *request = [NSURLRequest requestWithURL:url];
//AFNetworking asynchronous url request
AFJSONRequestOperation *operation = [AFJSONRequestOperation
                                     JSONRequestOperationWithRequest:request
                                     success:^(NSURLRequest *request, NSHTTPURLResponse *response, id responseObject)
                                     {

                                         self.locationsFromJSON = responseObject;
                                         [self.tableView reloadData];
                                     }
                                     failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id responseObject)
                                     {
                                         NSLog(@"Request Failed: %@, %@", error, error.userInfo);
                                     }];

[operation start];

}

Я также объявляю свойство Mutable Dictionary и свойство NSString для каждого значения в моем ответе JSON. В приведенном ниже методе TableVIewCell я беру объектный словарь, расположенный в index.row, считываю значения для ключей и присваиваю их свойствам метки ячейки-прототипа.

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

static NSString *CellIdentifier = @"locCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];    
if (cell == nil) {

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  reuseIdentifier:CellIdentifier];

}


self.dictObj = [[NSMutableDictionary alloc] init];
self.dictObj = [_locationsFromJSON objectAtIndex:indexPath.row];
cell.textLabel.text =  [_dictObj valueForKey:@"city"];  
cell.detailTextLabel.text = [_dictObj valueForKey:@"phone"];     
return cell;
}

ЭТО сработало! Просто потребовалось, чтобы кто-то еще указал на очевидное «похоже, у вас есть массив объектов словаря…».

person Tommy Alexander    schedule 14.05.2013