当我滚动到 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/