【问题标题】:Calling methods inside block and trying to reload data crash调用块内的方法并尝试重新加载数据崩溃
【发布时间】:2014-01-06 14:24:56
【问题描述】:

我使用 parse.com 作为后端,我的查询非常慢,所以我试图将其更改为使用块。

基本上,我的查询用我需要的一切填充一个数组,根据 if 语句,我在块内调用方法,这些方法填充我将在cellForRowAtIndexPath 中使用的数组。问题是当我尝试reloadDatainside 块时,应用程序崩溃了。

代码如下:

- (void)queryForTable {
    PFQuery *exerciciosQuery = [PFQuery queryWithClassName:@"ExerciciosPeso"];
    [exerciciosQuery whereKey:@"usuario" equalTo:[PFUser currentUser]];
    [exerciciosQuery includeKey:@"exercicio"];

    exerciciosQuery.cachePolicy = kPFCachePolicyCacheElseNetwork;

    [exerciciosQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

         [self configurarDatas];

         _seriesArray = objects;

            if (_seriesArray.count > 0) {
                NSPredicate *predIniciante = [NSPredicate predicateWithFormat:@"serie contains [cd] %@", @"Ini"];
                NSArray *arrayIniciante = [_seriesArray filteredArrayUsingPredicate:predIniciante];


                NSArray *arrayInicianteApenasSeries = arrayIniciante;
                NSArray *arrayInicianteApenasSeries2 = [arrayInicianteApenasSeries valueForKey:@"serie"];
                NSSet *setInicianteApenasSeries = [NSSet setWithArray:arrayInicianteApenasSeries2];
                NSArray *arrayInicianteCount = [setInicianteApenasSeries allObjects];

                if (arrayInicianteCount.count > 0) {
                    [self popularSeriesInicianteAB];
                // [self.tableView reloadData];


                }
                else if (arrayInicianteCount.count > 8) {

                    [self popularSeriesInicianteC];
                    //   [self.tableView reloadData];

                }
                else {

                    [self popularSeriesAvancado];
                    //   [self.tableView reloadData];
                    NSLog(@"POPULAR SERIES AVANÇADO");
                }
            }
    }];

}

我也尝试过使用dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; }); 重新加载数据,但效果不佳。

无论如何,我想如果我删除我的方法并将所有内容放入块中,它会起作用,但我不想这样做,因为使用 if 调用方法会使我的代码更容易遵循。

更新:

为了完整起见,这里是我的 DataSource 方法:

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
     {
     NSLog(@"numberOfRowsInSection %li", (unsigned long)_seriesForDisplay.count);
     return _seriesForDisplay.count;

 }


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
    static NSString *CellIdentifier = @"Cell";

    PFTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }





    PFObject *o = _seriesForDisplay[indexPath.row];
    // Texto da célula
    cell.textLabel.text = o[@"serieDisplay"];

    cell.detailTextLabel.text = o[@"grupos"];



    return cell;

}

【问题讨论】:

  • 不是你的问题(还),但[self popularSeriesInicianteC]; 永远不会被调用。
  • 试试这个:stackoverflow.com/a/7914335/653513 应该可以工作,如果你没有你的 populate... 方法也在后台工作。如果是这样,请在他们完成后致电reloadData... - 尽快。
  • 我试过这个,但得到了崩溃消息:空数组的索引 0 超出范围'。我试图在块内使用此代码。当我记录块内的数组时,似乎这些方法正在正确填充数组。
  • 您能否发布您的populate... 方法的代码。似乎他们也在单独的线程上工作......或者:你如何将数据传递给这些方法?他们是否有机会使用nil 数据?
  • 这是什么- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)objectdataSource 委托方法的奇怪签名...简单尝试:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

标签: ios objective-c uitableview objective-c-blocks parse-platform


【解决方案1】:

使用 Parse SDK 在 tableview 中实现数据有两种方式

  1. PFqueryTableViewController:你需要实现

    - (PFQuery *)queryForTable {
         return query;
      }
    
    - (PFObject *)objectAtIndex:(NSIndexPath *)indexPath {
      // overridden, since we want to implement sections
      }
    
     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: 
       (NSIndexPath *)indexPath object:(PFObject *)object {
      //get data: object
      }
    
     - (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:
     (NSIndexPath *)indexPath 
    
  2. UITableViewController/UIViewController 中的 UITableview:
    这是正常的方式,实现 uitableview 委托/数据源,你可以在这里编写一个类似 (void)queryForTable 的方法并调用 reloadData。

【讨论】:

  • 我试过这个,但得到了崩溃消息:空数组的索引 0 超出范围'。当我尝试重新加载数据时,数组仍然是空的。我尝试在块内使用此代码。
  • 您的问题不是来自主线程或后台线程中的 reloadData,我认为它来自您的数据源。显示更多代码:yourarray、numberRowAtIndexpath、cellForRowAtIndexPath
  • 你在使用 PFQueryTableViewController 吗?所以你需要实现一个(PFQuery)queryForTable 而不是(void)。如果你仍然没有清除它,你应该使用普通的 uitableview 而不是 PFquerytableview
【解决方案2】:

我使用的是PFQueryTableViewController,它来自 parse.com 后端并且有一些不同的方法。我将查询更改为void 并使用findObjectsInBackgroundWithBlock。因此,我的方法- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object 没有收到PFObjects,这就是我尝试reloadData 时崩溃的原因。

我把表改回UITableViewController

我在块内使用dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; });,它现在可以工作了。

这篇文章的答案很好,对我帮助很大。

【讨论】:

  • PFQueryTableViewController 是一条重要的信息 :) 很高兴听到您的成功。
【解决方案3】:

如果您不能保证块将在哪个线程上运行(如果它可以在后台线程上运行),那么您应该在执行任何 UI 更改之前切换到主线程。这可以通过performSelectorOnMainThread:withObject:waitUntilDone:dispatch_async(dispatch_get_main_queue(), ^{ 完成。

【讨论】:

  • 当我切换到主线程以重新加载数据时,我收到崩溃说我的数组是空的。
  • 当你重新加载你应该使用相同的数组来获取行数和获取单元格数据...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多