ios - 到达表底部时 TableView 出现错误

标签 ios iphone objective-c uitableview

当我滚动到 TableView 底部时,我收到此错误,我认为实际从服务器检索图片没有任何错误。:

 *** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (15) beyond bounds (15)'

这是我的 .m 文件,我将其剪切为仅文件中实际需要的部分:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections.
    return 1;
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row % 2 == 0)  {
        NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];
        NSString *created = [tweet objectForKey:@"created_at"];
        NSLog(@"%@", created);
        static NSString *CellIdentifier = @"TweetCell";

        UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }

        NSString *text = [tweet objectForKey:@"text"];
        NSString *name = [[tweet objectForKey:@"user"] objectForKey:@"name"];



        cell.textLabel.text = text;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"by %@", name];

        return cell;
    }else {
        static NSString *CellIdentifier = @"InstagramCell";
        UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];



        NSDictionary *entry = [self entries][indexPath.row];
        NSString *imageUrlString = entry[@"images"][@"low_resolution"][@"url"];
        NSURL *url = [NSURL URLWithString:imageUrlString];
        [cell.imageView setImageWithURL:url];
        return cell;
    }

}


- (void)fetchTweets {
    self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.twitter.com/1.1/"] key:@"TWEETER_KEY" secret:@"TWEETER_SECRET"];

    [self.twitterClient authorizeUsingOAuthWithRequestTokenPath:@"/oauth/request_token" userAuthorizationPath:@"/oauth/authorize" callbackURL:[NSURL URLWithString:@"floadt://success"] accessTokenPath:@"/oauth/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) {
        [self.twitterClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
        [self.twitterClient getPath:@"statuses/home_timeline.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
            NSArray *responseArray = (NSArray *)responseObject;
            [responseArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                NSLog(@"Success: %@", obj);
                tweets = responseArray;
                [self.tableView reloadData];
            }];
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"Error: %@", error);
        }];
    } failure:^(NSError *error) {
        NSLog(@"Error: %@", error);
    }];

}

最佳答案

numberOfRowsInSection 的返回值与代码在 cellForRowAtIndexPath 中执行的数组访问之间需要紧密协调。

考虑一下,您的条目数组和推文数组各有 4 个元素。因此,numberOfRowsInSection 返回 8。调用 cellForRowAtIndexPath 方法来配置第 6 行。您的代码将执行以下操作:NSDictionary *tweet = [tweets objectAtIndex:indexPath.row];

但是等等...该数组只有 4 个元素,对吧?在索引 6 处请求某些内容将导致您看到的崩溃。

编写一个方法将数组交错成一个数组可能会更简单,然后在 numberOfRowsInSection 中回答组合数组的计数。在 cellForRowAtIndexPath 中,数组元素本身应该能够告诉您拥有哪种类型的行(而不是索引)。取消引用组合数组并相应地配置表。

编辑 - 我会尝试在代码中更明确地表达我的建议:为了简单起见,假设“条目”和“推文”都是 NSDictionaries 数组,并且您的应用程序希望首先在 UI 条目中组织它们,然后是推文。

//在界面中:

@property (nonatomic, strong) NSArray *myModel;

//在代码中:

- (NSArray *)myModel {

    if (!_myModel) {
        NSMutableArray *array = [NSMutableArray arrayWithArray:[self entries]];
        [array addObjectsFromArray:tweets];
        _myModel = [NSArray arrayWithArray:array];
    }
    return _myModel;
}

我们称其为“myModel”是有原因的。这是表的数据源。数据源协议(protocol)明确询问此数组(而不是其他数组)。

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

现在,cellForRowAtIndexPath 将要求您配置那么多(myModel 计数)行,编号为 0..count-1。您必须为所有数据源方法取消引用同一数组 - myModel:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *myModelForThisRow = self.myModel[indexPath.row];
    // get the cell = deque...
    cell.textLabel.text = myModelForThisRow[@"someKey"];
    return cell;
}

如果您的推文或条目数组发生变化怎么办?没问题,只需像这样重建模型即可:

- (IBAction)tweetsOrEntriesDidChange:(id)sender {

    self.myModel = nil;          // the "lazy" getter will rebuild it
    [self.tableView reloadData]; // this will call the datasource which will call the lazy getter
}

关于ios - 到达表底部时 TableView 出现错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20039237/

相关文章:

ios - executefetchrequest 导致崩溃

ios - 当数据改变时如何调用函数?

ios - 苹果的44x44触摸尺寸最小;较小的高度和较长的宽度可以接受吗?

iphone - 将 HEX NSString 转换为 NSData

objective-c - 在 iPhone 的 Objective-C 中查找联系人图像的路径

ios - 在 iOS 中收到地理围栏事件 n 分钟后如何运行方法?

iphone - 如何访问对象 ID 标识属性?

iphone - 如何使用 ARC 知道 Objective C 中的对象是否存活

objective-c - xib中基于嵌套 View 的NSTableViews

ios - 如何检查 iPad 是否为 iPad Pro