Ios Tableview滚动崩溃应用程序
我正在开发一个iPhone应用程序,我在后台从服务器下载图像 这是我的申请表 当我点击Ios Tableview滚动崩溃应用程序,ios,iphone,objective-c,ipad,nsthread,Ios,Iphone,Objective C,Ipad,Nsthread,我正在开发一个iPhone应用程序,我在后台从服务器下载图像 这是我的申请表 当我点击按钮1时,我正在从服务器获取5个数据,也就是图像,当用户向上滚动时获取数据后,我再次从服务器获取新的5个数据,当用户向上滚动时,我正在从服务器获取新的5个数据,依此类推 在为按钮1获取数据时,如果我点击按钮2我将取消先前的按钮1线程,并为按钮2获取新的5个数据,然后再次滚动它,获取与按钮1相同的新的5个数据 但在重新加载tableview一段时间后,我的应用程序会崩溃并显示: 由于未捕获的异常“NSRange
按钮1
时,我正在从服务器获取5个数据,也就是图像,当用户向上滚动时获取数据后,我再次从服务器获取新的5个数据,当用户向上滚动时,我正在从服务器获取新的5个数据,依此类推
在为按钮1
获取数据时,如果我点击按钮2
我将取消先前的按钮1
线程,并为按钮2
获取新的5个数据,然后再次滚动它,获取与按钮1相同的新的5个数据
但在重新加载tableview一段时间后,我的应用程序会崩溃并显示:
由于未捕获的异常“NSRangeException”而终止应用程序,原因:'-[\uu NSArrayM objectAtIndex:]:索引28超出范围[0..4]
以下是我的代码片段:
- (void)viewDidLoad
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self fetchDataForButton1];
dispatch_async(dispatch_get_main_queue(), ^(void) {
[tableView reloadData];
});
});
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
if(it is last row then fetch new 5 data)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Code runs on background thread
[self LoadMoreData];
dispatch_async(dispatch_get_main_queue(), ^(void) {
//Code here is run on the main thread
[_tblList reloadData];
});
});
}else{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginBackgroundFetchTask];
[self downloadImage_3:indexPath];
[self endBackgroundFetchTask];
});
}
}
-(void)downloadImage_3:(NSIndexPath *)path{
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImagePath]]];
if (img) {
[dicImages_msg setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:@"Merchant_SmallImage"]];
}
[_tblList performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}
- (void) beginBackgroundFetchTask
{
self.backgroundFetchTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundFetchTask];
}];
}
- (void) endBackgroundFetchTask
{
[[UIApplication sharedApplication] endBackgroundTask: self.backgroundFetchTask];
self.backgroundFetchTask = UIBackgroundTaskInvalid;
NSLog(@"ended BackgroundFetchTask");
}
-(void)LoadMoreData
{
//Fetches new 5 data from server...
}
使用SDWebImage从服务器获取图像。根据您的日志数组只有5个计数,您正在按照
indexpath.row
获取数据,在这种崩溃情况下为28。因此,您可能正在根据新数组调整单元格indexpath行,该数组在滚动时一次又一次地获取数据,但重复5
只需放置一个断点并检查是否正在重置计数为[0 4]的indexpath行
更新:
[[NSThread currentThread] populateDataInBackground];
这是因为从服务器加载图像需要时间,而单元在分配时不会获得任何数据 您需要为它实现延迟加载
这是一个很好的教程。禁用用户交互,然后转到表格顶部:
[TableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
然后打电话:
[TableView reloadData];
然后启用用户交互。
希望能解决问题试试这个
1) 用于从服务器获取图像
2) 使用该功能获取下5个数据
这将有助于在后台获取数据。我不会从
cellforrowatinexpath
方法获取这样的数据。用于显示单元格的
而是这样做:
fetchLoadData
方法,然后等待- 将新的5个数据对象添加到数据数组中
- 使用
delegate方法更新节中的行数numberofrowsinssection
- 您将发现,一旦使用
[myTable reloadTable]刷新表格,如果编码正确,单元格将正确显示代码>
我认为问题可能出在
[self-downloadImage_3:indexath]
当您在Button1
调用dispatch\u async
时,并且dispatch\u async
块没有调用,然后单击Button2
,我猜msg\u array
被清除并填充新的5对象,然后调用dispatch\u async
块,块的path.row
是28,而msg_数组
有5个新对象的新数组内容,然后崩溃
您应该在单击其他按钮之前取消dispatch\u async
,这对于dispatch\u async
是不可能的,因此您可以在块中进行判断:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self beginBackgroundFetchTask];
[self downloadImage_3:indexPath buttonIndex:index];
[self endBackgroundFetchTask];
});
-(void)downloadImage_3:(NSIndexPath *)path buttonIndex:(int)buttonIndex{
if(self.currentSelectIndex != buttonIndex) return; //skip reloadData if not same index
UIImage *img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:ImagePath]]];
if (img) {
[dicImages_msg setObject:img forKey:[[msg_array objectAtIndex:path.row] valueForKey:@"Merchant_SmallImage"]];
}
[_tblList performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
}
尝试调试你的应用程序,在cellForRowAtIndexPath上设置断点。查看数组何时超出边界。您得到的错误是因为数组在特定的indexath.row上获取空值。原因:[[uuu nsarray-objectAtIndex:]:索引28超出边界[0..4],您试图访问索引28处的对象,但数组只有5个元素。您是对的,伙计,但是,当我单击按钮2时,我已经停止提取按钮1的数据,我正在初始化数组并再次提取按钮2的新数据,但是崩溃发生了,因为它仍然提取按钮1的数据,索引28是按钮1的,我应该如何停止按钮1的线程?单击
按钮2
为什么要将相同的响应复制并粘贴到每个答案上。这里的人都在帮你。对不起,伙计,我从过去4天就被困在这里,找不到答案:(你是对的,伙计,但是当我点击按钮2时,我已经停止提取按钮1的数据,我正在初始化我的数组并再次提取按钮2的新数据,但是崩溃发生了,因为它仍然提取按钮1的数据,索引28是按钮1的,我应该如何停止我的线程呢<代码>按钮1?点击按钮2
你是对的,伙计,但是当我点击按钮2
时,我已经停止提取按钮1
的数据,我正在初始化数组,并再次提取按钮2
的新数据,但是崩溃发生了,因为它仍然提取按钮1
的数据,索引28是无效的按钮1
我应该如何停止我的按钮1
线程?点击按钮2
你是对的,伙计,但是当我点击按钮2
时,我已经停止了提取按钮1
的数据,我正在初始化我的数组并再次提取按钮2
的新数据,但是崩溃发生了,因为它仍然存在获取按钮1的数据
索引28是按钮1的
如何停止按钮1的线程