Reputation: 859
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 NSDictionary
named 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:
Upvotes: 0
Views: 64
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