UITableView 数据仅在滚动时重新加载(有错误),并且无法正确重新加载数据



Background

我有一个处理 2 个UITableViewUIViewController,两者都带有自定义UITableViewCell子类。顶部表(类别)上的单击事件应该触发底部表(RSS 源中的文章列表)上的reloadData,具体取决于选择的类别。应该发生的是拉取新数据并重新填充相关数组,然后数据显示在底部表上。

要显示的数据是:

  • 一张图片
  • a UILabel(日期)
  • 标题的UITextView

1)第一个问题

启动应用程序时默认加载的列表可以正确加载(几乎,但我在 #2 中得到了"几乎"),但是一旦在顶部表中选择了类别,包含要在单元格中显示的数据的数组将使用相关数据重建,但 reloadData 方法不会立即调用所需的结果。只有向下滚动一次,然后向上滚动,新数据显示。使用调试,我可以看到数据正确加载到数组中,所以我确定这是一个UITableViewControllerUITableViewCell的问题。

我已经尝试了在StackOverflow上讨论的各种解决方案,除了明显的self.myTableView.reloadData最常见的两个是调用ReloadData,如下所示:

[self.myTableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];

还有

dispatch_async(dispatch_get_main_queue(), ^{
    [self.myTableView reloadData];});
}

每次我尝试从 ArticlesTableViewController 实例中调用这些时,都没有成功。

2)第二个问题

DateLabel 仅在打开应用程序时显示在第一个单元格上,然后要使 dateLabel 显示在其余单元格中,我实际上必须向下滚动,然后再次向上滚动。从上方返回视图的单元格包含 dateLabel,但如果单元格从下方重新出现在视图中,则它再次消失。非常令人困惑的东西。

这是我的相关代码

cellForRowAtIndexPathArticlesTableViewController):

// Method that gets fired when parsing is complete via NSNotification
- (void) parsingComplete {
//Tell the tableview to animate the changes automatically
    self.articleList = [[NSMutableArray alloc]initWithArray:parser.articles];
    [myTableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView     cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      static  NSString *CellIdentifier = @"Cell";
ArticlesTableViewCell *cell = (ArticlesTableViewCell *)[myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell){
 cell = [[ArticlesTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
dispatch_async(kBgQueue, ^{
      NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.articleList valueForKey:@"enclosure"] objectAtIndex:indexPath.row]]];
           if (imgData) {
        UIImage *image = [UIImage imageWithData:imgData];
        if (image) {
            dispatch_async(dispatch_get_main_queue(), ^{
                    cell.enclosure.image = image;
                [cell.enclosure setNeedsDisplay];
            });
        }
    }
});


    [cell.dateLabel setText:[[self.articleList valueForKey:@"pubDate"] objectAtIndex:indexPath.row]];
    [cell.headingTextView setText:[[self.articleList valueForKey:@"title"] objectAtIndex:indexPath.row]];
     cell.headingTextView.editable = NO;

return cell;
 }

自定义单元格代码(用于ArticlesTableViewCell):

    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
    {
            self = [super initWithStyle:style     reuseIdentifier:reuseIdentifier];
    if (self) {
        self.enclosure = [[UIImageView alloc] initWithFrame:CGRectMake(10,10,48,48)];
        self.enclosure.tag = 1;
         //self.imageView = nil;
        self.dateLabel = [[UILabel alloc] initWithFrame: CGRectMake (75,-10,50,50)];
        self.dateLabel.textColor = [UIColor grayColor];
        self.dateLabel.font = [UIFont fontWithName:@"Arial" size:8.0f];
        self.headingTextView= [[UITextView alloc] initWithFrame:CGRectMake(70, 20, 400, 80)];
        self.headingTextView.textColor = [UIColor blackColor];
        self.headingTextView.font = [UIFont fontWithName:@"Arial" size:10.0f];
     [self addSubview:self.dateLabel];
        [self addSubview:self.enclosure];
        [self addSubview:self.headingTextView];

        //Here the Date only appears in the first cell, but when I scroll down and up again it re-appears
            }
    return self;
}

编辑下面是CategoriesTableViewController(第一个表)中的CellForRowAtIndexPath代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    CatTableViewCell *cell = (CatTableViewCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[CatTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    cell.nameLabel.text = [categories objectAtIndex:indexPath.row];

    return cell;
   }

下面是 ViewController 中实例化这两个 tableViewController 的代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *categoryView = [[UIView alloc] init];
    [categoryView setFrame:CGRectMake(60,0, 100,-200)];
    UIView *articlesView = [[UIView alloc] init];
    [articlesView setFrame:CGRectMake(0,50, 400,400)];
    CatBarTVC *categoryBar = [[CatBarTVC alloc] initWithStyle:UITableViewStylePlain];
    categoryBar.view.transform = CGAffineTransformMakeRotation(-M_PI * 0.5);
    categoryBar.view.autoresizesSubviews=NO;

    ArticlesTVC *articles = [[ArticlesTVC alloc] initWithStyle:UITableViewStylePlain];
    [articlesView addSubview:articles.view];
    //[self addChildViewController:articles];
    //[articlesView addSubview:articles.view];
    [self.view addSubview:categoryBar.view];
    [self.view addSubview:articles.view];
    [self addChildViewController:categoryBar];
    [self addChildViewController:articles];
    categoryBar.view.frame =CGRectMake(0,0, 500,70);
    articles.view.frame =CGRectMake(0,50, 400,400);
}

我在代码中看到了许多问题。请查看代码中的注释:

- (UITableViewCell *)tableView:(UITableView *)tableView     cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Suggestion: Try to keep identifier in ArticlesTableViewCell if you want to use it in more than one table view controller. Don't use _tableView. _tableView is iVar. You should use it only in getters, setters and in init methods.
    static  NSString *CellIdentifier = @"Cell";
    // Don't call "self.myTableView" of one specific tableView but for current one that is apassed by argument (tableView).
    ArticlesTableViewCell *cell = (ArticlesTableViewCell *)[self.myTableView dequeueReusableCellWithIdentifier:CellIdentifier];
    // You override here existing cell. Try to use if(cell==nil) before creating new cell.
    cell = [[ArticlesTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    dispatch_async(kBgQueue, ^{
        NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[self.articleList valueForKey:@"enclosure"] objectAtIndex:indexPath.row]]];
        if (imgData) {
            UIImage *image = [UIImage imageWithData:imgData];
            if (image) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    // You should call [cell setNeedsDisplay to inform app that this view have to be redrawn.
                    cell.enclosure.image = image;
                });
            }
        }
    });
    // No need to call this on global quele. You should call this directly (e.g. cell.dataLabel = self.articleList[@"pubDate"][indexpath.row];)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [cell.dateLabel performSelectorOnMainThread:@selector(setText:) withObject:[[self.articleList valueForKey:@"pubDate"] objectAtIndex:indexPath.row] waitUntilDone:NO modes:@[NSRunLoopCommonModes]];
        [cell.headingTextView performSelectorOnMainThread:@selector(setText:) withObject:[[self.articleList valueForKey:@"title"] objectAtIndex:indexPath.row] waitUntilDone:NO modes:@[NSRunLoopCommonModes]];
        cell.headingTextView.editable = NO;
    });
    return cell;
}

最新更新