Tableview滚动崩溃应用程序

时间:2014-02-21 06:54:13

标签: ios iphone objective-c ipad nsthread

我正在开发iPhone应用程序,我在后台从服务器下载图像,

以下是我的申请表,

当我点击Button 1我从服务器也获取5个数据时,在用户向上滚动后获取数据后,当用户向上滚动时我再次从服务器获取新的5个数据我从服务器获取新的5个数据等等

在获取Button 1的数据时,如果我点击Button 2取消我之前的Button 1帖子,我正在为Button 2获取新的5个数据并再次滚动它获取新的5个数据与Button 1相同

但是在重新加载tableview之后一段时间我的应用程序崩溃并显示: 由于未捕获的异常'NSRangeException'而终止应用程序,原因:' - [__ 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...
}

7 个答案:

答案 0 :(得分:1)

试试这个

1)使用SDWebImage从服务器获取图像

2)使用Pull Refresher功能获取下5个数据。

这将有助于在后台获取数据。

答案 1 :(得分:1)

我认为问题可能是[self downloadImage_3:indexPath];您在dispatch_async时调用Button1并且dispatch_async块未调用,然后您点击{{1} },然后我猜Button2被清除并填充新的5对象,之后调用msg_array块,块的dispatch_async为28,而path.row有5个新对象的新数组内容,然后崩溃。

您应该在点击其他按钮之前取消msg_array,这对于dispatch_async是不可能的,因此您可以在块中做出判断:

dispatch_async

答案 2 :(得分:0)

使用SDWebImage从服务器获取图像。

答案 3 :(得分:0)

每个日志数组的AS只有5个计数,您按照indexpath.row获取数据,在此崩溃情况下 28 。因此,您可能正在根据新数组调整单元索引路径行,该数组一次又一次地获取滚动数据,但重复 5

只需设置一个断点并检查是否重置了 [0 4] 的数量的索引路径行;

<强>更新:

[[NSThread currentThread]  populateDataInBackground];

答案 4 :(得分:0)

这是因为图像从服务器加载需要时间,而单元格在分配时没有数据。

您需要为它实现延迟加载。

Here是一个很好的教程。

答案 5 :(得分:0)

禁用用户互动,然后转到桌面顶部:

 [TableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];

然后致电:

 [TableView reloadData];

然后启用用户交互。 希望能解决问题

答案 6 :(得分:0)

我不会从cellForRowAtIndexPath方法获取类似的数据。那用于显示单元格。

而是这样做:

  1. 列出您的原始数据。
  2. 当用户滚过最后一个单元格时,显示一个显示加载符号的页脚。
  3. 同时当页脚显示加载符号时,然后只调用fetchLoadData方法,然后等待
  4. 直到你没有收到服务器的声音,继续显示加载符号,不要开始添加新的单元格来准备任何事情,因为你可能要么不再获得数据,这时你必须摆脱页脚单元格,让用户知道没有更多数据要检索,或者如果有更多数据需要显示,那么按以下顺序执行以下操作设置下5个单元格:
    • 将新的5个数据对象添加到数据阵列
    • 使用numberOfRowsInSection委托方法
    • 更新部分中的行数
    • 使用[myTable reloadTable];
    • 刷新表格后,您会发现正确编码的单元格会正确显示