Chris Jenkins
Chris Jenkins

Reputation: 719

AFNetworking JSON to UITableView - Objective-C

I'm working on my first app and starting to bang my head against the wall. I created a C# web API that spits out simple JSON. I'm using AFNetworking and getting a valid response (I believe) and now I want to take this JSON object and turn it into a UITable. Here's the code.

This is on my view did load.

- (void)viewDidLoad
{
    [super viewDidLoad];

    KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"SMP" accessGroup:nil];
    NSString *password = [keychain objectForKey:(__bridge id)(kSecValueData)];
    NSString *username = [keychain objectForKey:(__bridge id)(kSecAttrAccount)];

    [[APIClient sharedManager] setUsername:username andPassword:password];

    [[APIClient sharedManager] getPath:@"/api/leads_calls/?$top=5&$orderby=CallStart%20desc"parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
        self.leads_dict = responseObject;
        self.leads_calls = [[NSMutableArray alloc] init];
        [self.leads_calls addObject:self.leads_dict];

        NSLog(@"%@", self.leads_calls);

        [self.tableView setHidden:NO];
        [self.tableView reloadData];

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        // error stuff here
    }];
}

I'm able to breakpoint inside the following code, and then an exception is thrown:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    if (self.leads_calls > nil) {
         // Here is where I get the exception
         cell.textLabel.text = [[self.leads_calls objectAtIndex:indexPath.row] objectForKey:@"CallerName"];
    }
    return cell;
}

And finally, my array at time of the exception looks like this:

2013-06-06 14:32:11.372 SMP[39846:c07] (
        (
        {
            CallEnd = "2013-06-06T12:20:26";
            CallStart = "2013-06-06T12:11:56";
            CallerName = "xx & xx";
            CallerNo = xxxxxxxxxx;
            Handled = 0;
            ID = 1134514;
        },
        {
            CallEnd = "2013-06-06T11:36:41";
            CallStart = "2013-06-06T11:07:43";
            CallerName = "Las xx    NV";
            CallerNo = xxxxxxxxxx;
            Handled = 0;
            ID = 1134333;
        },
        {
            CallEnd = "2013-06-04T13:09:00";
            CallStart = "2013-06-04T12:58:36";
            CallerName = "xx LAW FI";
            CallerNo = xxxxxxxxxx;
            Handled = 0;
            ID = 1129882;
        },
                {
            CallEnd = "2013-06-03T16:43:31";
            CallStart = "2013-06-03T16:32:32";
            CallerName = "xx xx";
            CallerNo = xxxxxxxxxx;
            Handled = 0;
            ID = 1127940;
        },
                {
            CallEnd = "2013-06-03T07:46:16";
            CallStart = "2013-06-03T07:44:23";
            CallerName = "xx x";
            CallerNo = xxxxxxxxxx;
            Handled = 0;
            ID = 1125648;
        }
    )
)

I'm going to go out on a limb and guess that cell.textLabel.text is getting a value it doesn't expect, but I'm not sure how to fix that.

Upvotes: 1

Views: 480

Answers (2)

Adam Waite
Adam Waite

Reputation: 18855

I think that you have just one NSDictionary object in your array rather than many.

The text property you are trying to set on the UILabel surely isn't an NSString as it's meant to be either.

What is the class of the responseObject?

Find out with:

NSLog(@"%@", [responseObject class]);

or in the debugger:

po [responseObject class]

Also:

self.leads_calls > nil is not a common convention in Objective-C. self.leads_calls.count > 0 is better

EDIT

ok, scrap the dictionary leads_dict and do self.leads_calls = responseObject

then in cellForRowAtIndexPath do:

cell.textLabel.text = [[self.leads_calls objectAtIndex:indexPath.row] objectForKey:@"CallerName"];

as you have already (realised after I typed ha)

EDIT 2

You need to implement UITableViewDelegate method

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.leads_calls.count;
}

To ensure that only the number of cells created in the UITableView matches the count of objects in the array.

If I were you I'd look into creating a model class for your response object too, it will make your life easier later on perhaps.

Upvotes: 1

Wain
Wain

Reputation: 119031

Painful to see, but you have dictionaries in and array in an array:

2013-06-06 14:32:11.372 SMP[39846:c07]
(
    (
        {

Notice there are 2 round brackets...

So, leads_dict isn't really a dictionary, it's an array of dictionaries. Having both leads_dict and leads_calls seems like overkill, remove one of them. Ensure that the one left is an array and use that to drive your table view.

Upvotes: 1

Related Questions