2013-08-06 43 views
1

我想從JSON解析對象後填充表視圖。我想將行數設置爲解析對象的數量。NSRangeException錯誤

這裏是我的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]; 

}

這裏是我的數據源的方法之一(我相信,誤差必須在這裏):

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

這裏是我的全部錯誤消息:

> *** 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

這裏是我的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; 
} 

更新2

我加了一些日誌項目,它提供了一些有趣的輸出:

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 block 2013-08-06 23:53:04.320 NotificationReader [1193:c07]有 14通知2013-08-06 23:53:08.260 NotificationReader [1193:c07] *由於未捕獲的異常而終止應用程序

所以首先它認爲我的數組是空的,然後重新加載並獲得正確的通知計數。不幸的是,它從未進入的cellForRowAtIndexPath方法..

更新3

我增加了一個異常斷點到我的項目,再加上做了一些額外的日誌記錄,和我假設,它在某種程度上有麻煩重裝表視圖。這是迄今爲止的效果:

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} 

堆棧跟蹤:

#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 

我嘗試使用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. 
+1

這種方法可以簡化爲' - (NSInteger的)的tableView: (UITableView *)tableView numberOfRowsInSection:(NSInteger)部分 { return [[self notifications] count]; }'具有完全相同的效果,並且不能在任何情況下導致該異常。正如消息所說,這是對「objectAtIndex:」的調用,其參數1正在提高。 –

+0

你可以在你的UITableViewDelegate方法中放置斷點並找出引發異常的那一行嗎? 您的'numberOfRowsInSection'委託似乎沒有任何問題。 –

+0

@Tarek我在viewDidLoad方法的頂部初始化通知。 –

回答

2

這是由於嘗試訪問超出數組邊界的索引而引起的。從外觀上看,唯一的陣列訪問是在-tableView:cellForRowAtIndexPath:

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

我希望這是引發異常的地方。

您可以通過在斷點導航器中添加「添加異常斷點...」來了解確定性。

通過確認[indexPath row][self notifications]數組的範圍內來解決此問題。或者,如果你期望這應該總是在範圍內,那麼找出爲什麼它可能會超出界限。

在一個側面說明,你可以重寫你的方法之一,如下所示:

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

如果self.notifications是零,則返回0。如果計數爲0,那麼它顯然會返回0。所有這些都是必需的。

編輯:最後,您還可以重寫使用下標數組訪問,如下所示:

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

確保您撥打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]); 
}]; 
0

提意見是正確的,你應該調試此類通過設置斷點並逐步完成代碼。用日誌語句補充這種方法。

你也應該在Xcode中設置一個「All Exceptions Breakpoint」(命令6,然後點擊左下角的+按鈕)。

該錯誤可能不會發生在numberOfRowsInSection。是它可能在cellForRowAtIndexPath發生,你做的事:

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

就像你做nilcount檢查numberOfRowsInSection你應該做同樣在這裏:

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

我的猜測是JSON響應是不是你期待它,因此self.notifications是不是你所期望的。

+0

感謝您的建議,我試着爲初學者做一些日誌記錄,請查看更新後的結果文章。 –

0

在不同的機器上運行代碼後,它似乎一切工作,因爲它應該。我的配置中肯定有一些垃圾,所以我再次添加了項目並確認它正在工作。 謝謝大家回覆! @Sam,特別感謝您的測試和耐心!

0

Sam's answer是優秀的,但即使是這樣,他提到沒有爲我工作,直到我意識到我Table viewContent設置爲Static Cells,而不是Dynamic Prototypes故事板一切! dynamic-prototypes-table-view

即使你定義自己的numberOfRowsInSection這樣的:

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

如果不是動態的,沒準它會失敗;)