UITableView数组返回错误'索引0超出空数组的边界'

时间:2014-06-09 01:16:07

标签: ios objective-c json uitableview

我已经在我的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"
        }
    ]
}

1 个答案:

答案 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"];