Ghobs
Ghobs

Reputation: 859

Unable to populate UITableViewCells with contents of NSDictionary

I have my iOS app set up to receive JSON from some Parse cloud code. Based on what I'm seeing in the image below, the JSON consists of an NSDictionarynamed matchCenterDictionary, containing 3 NSArray objects named Top 3, which further each contain an NSDictionary with 4 key/value pairs.

What I want to do is create a new section in my UITableView for every instance of Top 3 that appears in the matchCenterDictionary, and populate the 3 cells of every respective section with the 4 key/value pairs info (title, price, imgurl, etc).

When I run the simulation, the app crashes and points to:

cell.textLabel.text = [[[_matchCenterDictionary objectForKey:@"Top 3"] objectAtIndex:0] objectForKey:@"Title"];

as the problem area, which means I'm not referencing it correctly. Code, error message, and screenshot are below.

MatchCenterViewController.m:

#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>

@interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *matchCenter;
@end

@implementation MatchCenterViewController


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}


- (void)viewDidLoad
{
    [super viewDidLoad];

    self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewCellStyleSubtitle];
    self.matchCenter.frame = CGRectMake(0,50,320,self.view.frame.size.height-100);
    _matchCenter.dataSource = self;
    _matchCenter.delegate = self;
    [self.view addSubview:self.matchCenter];

    self.matchCenterDictionary = [[NSDictionary alloc] init];
}

- (void)viewDidAppear:(BOOL)animated
{
    self.matchCenterDictionary = [[NSDictionary alloc] init];

    [PFCloud callFunctionInBackground:@"MatchCenterTest"
                       withParameters:@{
                                        @"test": @"Hi",
                                        }
                                block:^(NSDictionary *result, NSError *error) {

                                    if (!error) {
                                        self.matchCenterDictionary = [result objectForKey:@"MatchCenter"];
                                        [_matchCenter reloadData];

                                        NSLog(@"Result: '%@'", result);
                                    }
                                }];
}


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return _matchCenterDictionary.count;
}

//the part where i setup sections and the deleting of said sections

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 21.0f;
}



- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 21)];
    headerView.backgroundColor = [UIColor lightGrayColor];

//    _searchTerm = [[self.matchCenterArray firstObject] objectForKey:@"Search Term"];

    UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 0, 250, 21)];
//    headerLabel.text = [NSString stringWithFormat:@"%@", searchTerm];
//    headerLabel.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize]];
//    headerLabel.textColor = [UIColor whiteColor];
    headerLabel.backgroundColor = [UIColor lightGrayColor];
    [headerView addSubview:headerLabel];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.tag = section + 1000;
    button.frame = CGRectMake(300, 2, 17, 17);
    [button setImage:[UIImage imageNamed:@"xbutton.png"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(deleteButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [headerView addSubview:button];
    return headerView;
}



- (IBAction)deleteButtonPressed:(UIButton *)sender {
    NSLog(@"Search Term: '%@'", _searchTerm);

    [PFCloud callFunctionInBackground:@"deleteFromMatchCenter"
                       withParameters:@{
                                        @"searchTerm": _searchTerm,
                                       }
                                block:^(NSDictionary *result, NSError *error) {

                                    if (!error) {
                                        NSLog(@"Result: '%@'", result);
                                    }
                                }];
}




- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
     return 3;
}



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Initialize cell
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        // if no cell could be dequeued create a new one
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }



    // populate dictionary with results

    //NSDictionary *matchCenterDictionary= [_matchCenterArray objectAtIndex:indexPath.row];

    // title of the item
    cell.textLabel.text = [[[_matchCenterDictionary objectForKey:@"Top 3"] objectAtIndex:0] objectForKey:@"Title"];
    cell.textLabel.font = [UIFont boldSystemFontOfSize:12];

    // price of the item
    cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@", [[[_matchCenterDictionary objectForKey:@"Top 3"] objectAtIndex:0] objectForKey:@"Price"]];
    cell.detailTextLabel.textColor = [UIColor colorWithRed:0/255.0f green:127/255.0f blue:31/255.0f alpha:1.0f];

    // image of the item
    NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[[_matchCenterDictionary objectForKey:@"Top 3"] objectAtIndex:0] objectForKey:@"Image URL"]]];
    [[cell imageView] setImage:[UIImage imageWithData:imageData]];
    //imageView.frame = CGRectMake(45.0,10.0,10,10);

    return cell;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


/*
#pragma mark - Navigation

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

Error message:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0xaa1a6e0'
*** First throw call stack:
(
    0   CoreFoundation                      0x02a8d1e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x0264b8e5 objc_exception_throw + 44
    2   CoreFoundation                      0x02b2a243 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
    3   CoreFoundation                      0x02a7d50b ___forwarding___ + 1019
    4   CoreFoundation                      0x02a7d0ee _CF_forwarding_prep_0 + 14
    5   Parse+Storyboard                    0x00006129 -[MatchCenterViewController tableView:cellForRowAtIndexPath:] + 313
    6   UIKit                               0x0140411f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
    7   UIKit                               0x014041f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
    8   UIKit                               0x013e5ece -[UITableView _updateVisibleCellsNow:] + 2428
    9   UIKit                               0x013fa6a5 -[UITableView layoutSubviews] + 213
    10  UIKit                               0x0137a964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
    11  libobjc.A.dylib                     0x0265d82b -[NSObject performSelector:withObject:] + 70
    12  QuartzCore                          0x0065045a -[CALayer layoutSublayers] + 148
    13  QuartzCore                          0x00644244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    14  QuartzCore                          0x006440b0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
    15  QuartzCore                          0x005aa7fa _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
    16  QuartzCore                          0x005abb85 _ZN2CA11Transaction6commitEv + 393
    17  QuartzCore                          0x005ac258 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
    18  CoreFoundation                      0x02a5536e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    19  CoreFoundation                      0x02a552bf __CFRunLoopDoObservers + 399
    20  CoreFoundation                      0x02a33254 __CFRunLoopRun + 1076
    21  CoreFoundation                      0x02a329d3 CFRunLoopRunSpecific + 467
    22  CoreFoundation                      0x02a327eb CFRunLoopRunInMode + 123
    23  GraphicsServices                    0x02cea5ee GSEventRunModal + 192
    24  GraphicsServices                    0x02cea42b GSEventRun + 104
    25  UIKit                               0x0130bf9b UIApplicationMain + 1225
    26  Parse+Storyboard                    0x000024ed main + 141
    27  libdyld.dylib                       0x038e66d9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

JSON structure:

enter image description here

Upvotes: 0

Views: 64

Answers (1)

meda
meda

Reputation: 45490

Look at your screenshot again.

You have an array of dictionaries.

_matchCenterDictionary should be an NSArray.

Change

cell.textLabel.text = [[[_matchCenterDictionary objectForKey:@"Top 3"]
                                            objectAtIndex:0] objectForKey:@"Title"];

to

cell.textLabel.text = [[[_matchCenterArray  objectAtIndex:0] 
                                      objectForKey:@"Top 3"] objectForKey:@"Title"];

or shorter

cell.textLabel.text = _matchCenterArray[0][@"Top 3"][@"Title"];

When the JSON is too nested you can break it down to make it clearer

NSDictionary *top3 = _matchCenterArray[0];
NSString *title = top3[@"Title"];
cell.textLabel.text = title;

Upvotes: 1

Related Questions