代码之家  ›  专栏  ›  技术社区  ›  ACoolie

自动展开UITableView-NSrangeException

  •  3
  • ACoolie  · 技术社区  · 16 年前

    我有一个SQLite数据库绑定到我的UITableView。大约有2000行,所以我首先检索25行。一旦我滚动到列表的末尾,我希望它能自动检索25行。

    这是我现在使用的方法。忽略如果我加载所有2000行会发生什么,我稍后会担心这一点。在 tableView:numberOfRowsInSection: 我返回的行数超过了当前加载的行数。然后在 tableView:cellForRowAtIndexPath: 如果加载最后一行,我将加载更多行。

    通常我可以写几页,但最终我会得到一个例外: *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index (10) beyond bounds (10)' . 索引总是8-10。我不知道它是什么阵列,但我的 rows indices 数组中有10个以上的项。

    表视图:cellForRowatindexPath:

    if(indexPath.row >= [rows count]) {
        [cell.textLabel setText:@"Loading..."];
        if(!updating && indexPath.row == [rows count]) {
            updating = YES;
            [[self tableView] beginUpdates];
            NSMutableArray *indices = [NSMutableArray array];
            // stmt = ...
            while(sqlite3_step(stmt) == SQLITE_ROW) {
                [rows addObject:@"..."];
                [indices addObject:[NSIndexPath indexPathForRow:[rows count]-1 inSection:0]];
            }
            [[self tableView] insertRowsAtIndexPaths:indices withRowAnimation:UITableViewRowAnimationNone];
            [[self tableView] endUpdates];
            updating = NO;
        }
        return cell;
    }
    

    堆栈跟踪:

    #0  0x01ce4004 in ___TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION___ ()
    #1  0x9779df49 in objc_exception_throw ()
    #2  0x01cc5c3b in +[NSException raise:format:arguments:] ()
    #3  0x01cc5b9a in +[NSException raise:format:] ()
    #4  0x00072cc9 in _NSArrayRaiseBoundException ()
    #5  0x00010227 in -[NSCFArray objectAtIndex:] ()
    #6  0x0047fe5b in -[_UITableViewUpdateSupport(Private) _setupAnimationsForExistingVisibleCells] ()
    #7  0x0047f9e0 in -[_UITableViewUpdateSupport initWithTableView:updateItems:oldRowData:newRowData:oldRowRange:newRowRange:context:] ()
    #8  0x002eca2b in -[UITableView(_UITableViewPrivate) _updateWithItems:withOldRowData:oldRowRange:newRowRange:context:] ()
    #9  0x002ec757 in -[UITableView(_UITableViewPrivate) _endCellAnimationsWithContext:] ()
    #10 0x002def56 in -[UITableView endUpdates] ()    
    
    2 回复  |  直到 10 年前
        1
  •  4
  •   Alex    16 年前

    我有点不清楚为什么要插入行。在我看来,你让事情变得比需要的要复杂得多。 UITableView 只会要求您为屏幕上的表格单元格输入值(或很快会)。此外,通过不断向表视图添加行,滚动条不会反映用户在数据集中的实际位置。

    返回 tableView:numberOfRowsInSection: (您可以使用sqlite COUNT 聚合函数在不实际获取所有数据的情况下执行此操作,并在遇到“缓存未命中”时根据需要缓存其他数据(使用与上面类似的方法)。

    不过,如果我不得不猜测这段代码为什么会给您带来问题,那就是当表视图等待您返回单元格时,您正在修改表视图的内容。

    我建议你做一些看起来更像这样的事情:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        if ([indexPath row] >= [cache count]) {
            // Load additional items into the cache
        }
    
        // Do the regular cell setup stuff here; you can assume the data you need is available
        return cell;
    }
    
        2
  •  0
  •   ACoolie    16 年前

    亚历克斯,我接受你的回答,尽管我仍然对什么导致了实际的异常感兴趣。

    您在返回单元格时更新TableView的意见导致我实现 - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 在需要时加载更多的行,这更稳定,尽管我必须在单独的线程中这样做才能获得任何性能。

    您的解决方案也有效,而且肯定比我当前的方法简单。我必须决定是否要滚动条显示 实际的 位置或更有形的位置。至少对我来说,当滚动条这么小的时候,感觉应用程序正在加载许多对象,因此速度较慢。