简体   繁体   English

NSRangeException错误

[英]NSRangeException Error

I am trying to populate a table view after parsing objects from JSON. 我正在尝试从JSON解析对象后填充表格视图。 I want to set the number of rows to the count of the parsed objects. 我想将行数设置为已分析对象的数量。

Here's my viewDidLoad code: 这是我的viewDidLoad代码:

    - (void)viewDidLoad
{
[super viewDidLoad];

// initializing data source
[self setNotifications:[[NSMutableArray alloc] init]];

NSURL *url = [NSURL URLWithString:SourceURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];


AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

    [self setNotifications:[JSON objectForKey:@"notifications"]];
    //  [[self tableView] setHidden:NO];
    [[self tableView] reloadData];



} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
    NSLog(@"Request Failure Because %@",[error userInfo]);
}];

[operation start];

} }

Here is one of my datasource methods (I believe the error must be here): 这是我的数据源方法之一(我相信错误一定在这里):

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if ([self notifications] && [[self notifications] count] ) {
        return [[self notifications] count];
    } else{
        return 0;
    }
}

And here is my full error message: 这是我的完整错误消息:

> *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 ..
> 0]'
> *** First throw call stack: (0x13c4012 0x118ce7e 0x1379b44 0x510c04 0x300ea0 0x2b5c4e 0x2b8224 0x17c952 0x17c2dc 0xc4a9d14 0x26e0 0x16ea2
> 0x18409 0x162753f 0x1639014 0x16297d5 0x136aaf5 0x1369f44 0x1369e1b
> 0x22647e3 0x2264668 0xd0ffc 0x1f1d 0x1e45) libc++abi.dylib: terminate
> called throwing an exception

UPDATE : 更新

Here is my cellForRowAtIndexpath method: 这是我的cellForRowAtIndexpath方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"readNotification";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if (!cell){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
    }

    NSDictionary *notification = [[self notifications] objectAtIndex:[indexPath row]];
    [[cell textLabel] setText:[notification objectForKey:@"from"]];
    [[cell detailTextLabel] setText:[notification objectForKey:@"date"]];
    return cell;
}

UPDATE 2 更新2

I added some logs to the project, and it provided some interesting output: 我向项目添加了一些日志,它提供了一些有趣的输出:

2013-08-06 23:53:03.994 NotificationReader[1193:c07] 1. before request 2013-08-06 23:53:04.023 NotificationReader[1193:c07] 2. json parshing operation started 2013-08-06 23:53:04.031 NotificationReader[1193:c07] 3. entered the numberOfRowsInSection block 2013-08-06 23:53:04.040 NotificationReader[1193:c07] No notifications 2013-08-06 23:53:04.319 NotificationReader[1193:c07] 3. entered the numberOfRowsInSection block 2013-08-06 23:53:04.320 NotificationReader[1193:c07] There were 14 notifications 2013-08-06 23:53:08.260 NotificationReader[1193:c07] * Terminating app due to uncaught exception 2013-08-06 23:53:03.994 NotificationReader [1193:c07] 1.要求之前2013-08-06 23:53:04.023 NotificationReader [1193:c07] 2. json parshing操作已开始2013-08-06 23:53 :04.031 NotificationReader [1193:c07] 3.输入numberOfRowsInSection块2013-08-06 23:53:04.040 NotificationReader [1193:c07]无通知2013-08-06 23:53:04.319 NotificationReader [1193:c07] 3。输入了numberOfRowsInSection块2013-08-06 23:53:04.320 NotificationReader [1193:c07]共有14条通知2013-08-06 23:53:08.260 NotificationReader [1193:c07] *由于未捕获的异常而终止应用程序

So first it thinks that my array is empty, then it reloads and gets the count of notifications right. 因此,首先认为我的数组为空,然后重新加载并正确获取通知计数。 Unfortunately, it never enters the cellForRowAtIndexPath method.. 不幸的是,它永远不会进入cellForRowAtIndexPath方法。

UPDATE 3 更新3

I have added an exception breakpoint to my project, plus did some additional logging, and I'm assuming, it somehow has trouble reloading the table view. 我已经在项目中添加了一个异常断点,并进行了一些额外的日志记录,我假设它在某种程度上无法重新加载表视图。 Here is the outcome so far: 到目前为止,结果如下:

2013-08-07 08:40:58.104 NotificationReader[433:c07] 1. before request
2013-08-07 08:40:58.107 NotificationReader[433:c07] 2. json parshing operation started
2013-08-07 08:40:58.113 NotificationReader[433:c07] 3. entered the numberOfRowsInSection block
2013-08-07 08:40:58.120 NotificationReader[433:c07] Found 0 notifications!
2013-08-07 08:41:10.852 NotificationReader[433:c07] Trying to reload data
2013-08-07 08:41:10.853 NotificationReader[433:c07] data needs to be reloaded
2013-08-07 08:41:10.854 NotificationReader[433:c07] 3. entered the numberOfRowsInSection block
2013-08-07 08:41:10.855 NotificationReader[433:c07] Found 14 notifications!
2013-08-07 08:41:10.858 NotificationReader[433:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x13c5012 0x118de7e 0x137ab44 0x511c04 0x301ea0 0x2b6c4e 0x2b9224 0x17d952 0x17d2dc 0xc4c0d14 0x351b 0x162853f 0x163a014 0x162a7d5 0x136baf5 0x136af44 0x136ae1b 0x22657e3 0x2265668 0xd1ffc 0x2c4d 0x2b75)
libc++abi.dylib: terminate called throwing an exception}

Stack trace: 堆栈跟踪:

#0  0x0118de52 in objc_exception_throw ()
#1  0x0137ab44 in -[__NSArrayI objectAtIndex:] ()
#2  0x00511c04 in -[UITableViewDataSource tableView:heightForRowAtIndexPath:] ()
#3  0x00301ea0 in -[UITableViewController tableView:heightForRowAtIndexPath:] ()
#4  0x002b6c4e in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:] ()
#5  0x002b9224 in -[UITableViewRowData numberOfRows] ()
#6  0x0017d952 in -[UITableView noteNumberOfRowsChanged] ()
#7  0x0017d2dc in -[UITableView reloadData] ()
#8  0x0c4a9d14 in -[UITableViewAccessibility(Accessibility) reloadData] ()
#9  0x0000351b in __36-[NRTableViewController viewDidLoad]_block_invoke_2 at /Users/jozsef/Development/NotificationReader/NotificationReader/NRTableViewController.m:52

I tried using lldb with this result: 我尝试使用lldb并得到以下结果:

(lldb) po [[self notifications] count]
error: Execution was interrupted, reason: Attempted to dereference an invalid pointer..
The process has been returned to the state before execution.

This is caused by trying to access an index beyond the bounds of an array. 这是由于尝试访问超出数组范围的索引而引起的。 By the look of things, the only array access is in -tableView:cellForRowAtIndexPath: : 从外观上看,唯一的数组访问位于-tableView:cellForRowAtIndexPath:

NSDictionary *notification = [[self notifications] objectAtIndex:[indexPath row]];

I expect this is where the exception is raised. 我希望这是引发异常的地方。

You can find out for certain by adding a "Add Exceptions Breakpoint..." from the breakpoints navigator. 您可以通过在断点导航器中添加“添加例外断点...”来确定。

Fix this by confirming that [indexPath row] is within the bounds of the [self notifications] array. 通过确认[indexPath row][self notifications]数组的范围内来解决此问题。 Or if you expect this should always be within the bounds, then figure out why it could be out of bounds. 或者,如果您希望此值始终在范围之内,请弄清楚为什么它可能超出范围。

On a side note, you could rewrite one of your methods as follows: 附带说明一下,您可以按以下方式重写其中一种方法:

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

If self.notifications is nil, this will return 0. If count is 0, then it will obviously return 0. So that's all that is required. 如果self.notifications为nil,则将返回0。如果count为0,则显然将返回0。所以这就是全部。

EDIT: Finally, you could also rewrite the array access using subscripting, as follows: 编辑:最后,您还可以使用下标重写数组访问,如下所示:

NSDictionary *notification = self.notifications[indexPath.row];

Make sure you call the UI updates on the main thread in the success block of AFJSONRequestOperation, ie 确保在AFJSONRequestOperation成功块中的主线程上调用UI更新,即

AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {

    // update on the main thread!
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setNotifications:[JSON objectForKey:@"notifications"]];
        //  [[self tableView] setHidden:NO];
        [[self tableView] reloadData];
    });        

} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
    NSLog(@"Request Failure Because %@",[error userInfo]);
}];

The commenters are correct, you should debug this sort of thing by setting breakpoints and stepping through the code. 评论者是正确的,您应该通过设置断点并单步执行代码来调试这种事情。 Supplement this approach with log statements. 用日志语句补充此方法。

You should also set an "All Exceptions Breakpoint" in Xcode (command-6 and then hit the + button at the bottom left). 您还应该在Xcode中设置“所有异常断点”(命令6,然后单击左下方的+按钮)。

The error is likely NOT happening in numberOfRowsInSection . 该错误可能没有在numberOfRowsInSection发生。 Is it probably occurring in cellForRowAtIndexPath where you do: 它可能发生在您执行的cellForRowAtIndexPath中:

NSDictionary *notification = [[self notifications] objectAtIndex:[indexPath row]];

Just as you do nil and count checking in numberOfRowsInSection you should do the same here: 就像您在numberOfRowsInSection执行nilcount检查一样,您应该在此处执行相同的操作:

if (self.notifications) {
    if (indexPath.row < [self.notifications count]) {
        NSDictionary *notification = [[self notifications] objectAtIndex:[indexPath row]];`
        //...
    }
}

My guess is that the JSON response isn't what you're expecting it to be and therefore self.notifications isn't what you'd expect it to be. 我的猜测是JSON响应不是您期望的,因此self.notifications不是您期望的。

After running the code on different machines, it all seemed to work as it should. 在不同的机器上运行代码后,一切似乎都可以正常工作。 There must have been some junk in my configuration, so I added the project again and can confirm that it's working. 我的配置中肯定有一些垃圾,因此我再次添加了该项目,并可以确认它正在运行。 Thank you for everyone who responded! 谢谢大家的回应! @Sam, special thanks to you for your testing and patience! @Sam,特别感谢您的测试和耐心!

Oh Sam's answer is excellent, but even doing everything he mentioned didn't work out for me until I realize that my Table view had Content set to Static Cells instead of Dynamic Prototypes in my storyboard ! Oh Sam的回答非常好,但是即使我做他提到的所有事情对我也不起作用,直到我意识到我的Table view Storyboard中的 Content设置为Static Cells而不是Dynamic Prototypes 动态的原型表视

Even if you define your own numberOfRowsInSection like this: 即使您这样定义自己的numberOfRowsInSection

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

If it's not dynamic, chances it will fail ;) 如果它不是动态的,则可能会失败;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM