我已经在我的MatchCenterViewController中以编程方式创建了一个UITableView,但它似乎没有填充我的云代码函数返回的JSON数据。它崩溃并给我以下错误:
2014-06-08 20:56:23.762 Parse+Storyboard[9136:607] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(
0 CoreFoundation 0x02a8c1e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x0264a8e5 objc_exception_throw + 44
2 CoreFoundation 0x02a408b2 -[__NSArrayI objectAtIndex:] + 210
3 Parse+Storyboard 0x00005e6a -[MatchCenterViewController tableView:cellForRowAtIndexPath:] + 218
4 UIKit 0x0140311f -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 412
5 UIKit 0x014031f3 -[UITableView _createPreparedCellForGlobalRow:] + 69
6 UIKit 0x013e4ece -[UITableView _updateVisibleCellsNow:] + 2428
7 UIKit 0x013f96a5 -[UITableView layoutSubviews] + 213
8 UIKit 0x01379964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
9 libobjc.A.dylib 0x0265c82b -[NSObject performSelector:withObject:] + 70
10 QuartzCore 0x0064f45a -[CALayer layoutSublayers] + 148
11 QuartzCore 0x00643244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
12 QuartzCore 0x006430b0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
13 QuartzCore 0x005a97fa _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
14 QuartzCore 0x005aab85 _ZN2CA11Transaction6commitEv + 393
15 QuartzCore 0x006685b0 +[CATransaction flush] + 52
16 UIKit 0x013089bb _UIApplicationHandleEventQueue + 13095
17 CoreFoundation 0x02a1577f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
18 CoreFoundation 0x02a1510b __CFRunLoopDoSources0 + 235
19 CoreFoundation 0x02a321ae __CFRunLoopRun + 910
20 CoreFoundation 0x02a319d3 CFRunLoopRunSpecific + 467
21 CoreFoundation 0x02a317eb CFRunLoopRunInMode + 123
22 GraphicsServices 0x02ce95ee GSEventRunModal + 192
23 GraphicsServices 0x02ce942b GSEventRun + 104
24 UIKit 0x0130af9b UIApplicationMain + 1225
25 Parse+Storyboard 0x00002b4d main + 141
26 libdyld.dylib 0x038e56d9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
据我所知,它告诉我self.matchCenterArray
是空的,但我似乎无法弄清楚为什么数组没有填充返回的JSON。
MatchCenterViewController.h:
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "AsyncImageView.h"
#import "SearchViewController.h"
@interface MatchCenterViewController : UIViewController <UITableViewDataSource>
@property (nonatomic) IBOutlet NSString *itemSearch;
@property (nonatomic, strong) NSArray *imageURLs;
@property (strong, nonatomic) NSString *matchingCategoryCondition;
@property (strong, nonatomic) NSString *matchingCategoryLocation;
@property (strong, nonatomic) NSNumber *matchingCategoryMaxPrice;
@property (strong, nonatomic) NSNumber *matchingCategoryMinPrice;
@property (strong, nonatomic) NSArray *matchCenterArray;
@end
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) {
// self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
// _matchCenter.dataSource = self;
// _matchCenter.delegate = self;
// [self.view addSubview:self.matchCenter];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.matchCenter registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
_matchCenter.dataSource = self;
_matchCenter.delegate = self;
[self.view addSubview:self.matchCenter];
self.matchCenterArray = [[NSArray alloc] init];
}
- (void)viewDidAppear:(BOOL)animated
{
self.matchCenterArray = [[NSArray alloc] init];
[PFCloud callFunctionInBackground:@"MatchCenterTest"
withParameters:@{
@"test": @"Hi",
}
block:^(NSDictionary *result, NSError *error) {
if (!error) {
self.matchCenterArray = [result objectForKey:@"Top 3"];
dispatch_async(dispatch_get_main_queue(), ^{
[_matchCenter reloadData];
});
NSLog(@"Test Result: '%@'", result);
}
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *matchCenterDictionary= [self.matchCenterArray objectAtIndex:indexPath.row];
cell.textLabel.text = [matchCenterDictionary objectForKey:@"Title"];// title of the first object
// if([matchCenterDictionary objectForKey:@"Price"] != NULL)
// {
// cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@",[matchCenterDictionary objectForKey:@"Price"]];
// }
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before 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
返回的JSON:
{
"Top 3" : [
{
"Title" : "Apple iPhone 5s (Latest Model) - 16GB - Silver (AT&T) Smartphone",
"Price" : "400.0",
"Image URL" : "http://thumbs2.ebaystatic.com/m/mewfVG0QbBiu1nZytMuAlZw/140.jpg",
"Item URL" : "http://www.ebay.com/itm/Apple-iPhone-5s-Latest-Model-16GB-Silver-AT-T-Smartphone-/181431570117?pt:Cell_Phones"
},
{
"Title" : "Apple iPhone 5c (Latest Model) - 16GB - Pink (Verizon) Smartphone",
"Price" : "350.0",
"Image URL" : "http://thumbs4.ebaystatic.com/m/mMPAT67KjfCZF9oorbTf3uw/140.jpg",
"Item URL" : "http://www.ebay.com/itm/Apple-iPhone-5c-Latest-Model-16GB-Pink-Verizon-Smartphone-/191204844039?pt:Cell_Phones"
},
{
"Title" : "Apple iPhone 5 16GB, White, works with Virgin Mobile US NEW",
"Price" : "359.99",
"Image URL" : "http://thumbs3.ebaystatic.com/m/m5x1uj1iSS2fr691tifrvrw/140.jpg",
"Item URL" : "http://www.ebay.com/itm/Apple-iPhone-5-16GB-White-works-Virgin-Mobile-US-NEW-/141227441998?pt:Cell_Phones"
}
]
}
答案 0 :(得分:4)
UITableView将在API调用返回数据之前请求单元格。网络请求可能需要很长时间,如果用户未连接到网络,则会完全失败。不要认为您的网络电话会立即返回。
因为只在viewDidAppear:
启动异步(!)API调用,所以tableView甚至在启动API调用之前就开始请求单元格。
由于您已指定第一部分中有3行tableView:cellForRowAtIndexPath:
尝试访问此行:
// for first row
NSDictionary *matchCenterDictionary= [self.matchCenterArray objectAtIndex:0];
由于您的数组为空,并且在索引0处没有对象,因此会引发超出范围的异常。
如果数组中没有3个对象,请不要在tableView:numberOfRowsInSection:
中返回3,返回数组中包含的实际对象数:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.matchCenterArray count];
}
并且为了防止您的下一次崩溃,请将您注册单元格的调用移动到self.matchCenter不为nil的位置,即在tableView的alloc init之后。
e.g:
self.matchCenter = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
/* ... */
[self.matchCenter registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];