Ios UITableView数据仅在我滚动时重新加载(带有bug),并且我无法正确地重新加载数据 出身背景

Ios UITableView数据仅在我滚动时重新加载(带有bug),并且我无法正确地重新加载数据 出身背景,ios,objective-c,uitableview,Ios,Objective C,Uitableview,我有一个UIViewController,它处理2个UITableViews,这两个都带有自定义的UITableViewCell子类。顶部表格(类别)上的单击事件应触发底部表格(RSS提要中的文章列表)上的重新加载数据,具体取决于选择的类别。应该发生的是提取新数据并重新填充相关数组,然后数据显示在底部表格中 要显示的数据是: 形象 aui标签(用于日期) 标题的UITextView 1) 第一个问题 启动应用程序时默认加载的列表会正确加载(很好,但我会进入#2中的“几乎”),但一旦在顶部表格

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

要显示的数据是:

  • 形象
  • a
    ui标签
    (用于日期)
  • 标题的
    UITextView
1) 第一个问题 启动应用程序时默认加载的列表会正确加载(很好,但我会进入#2中的“几乎”),但一旦在顶部表格中选择了一个类别,包含要在单元格中显示的数据的数组将使用相关数据重建,但是
reloadData
方法不会立即调用所需的结果。只有向下滚动一次,然后再向上滚动,新数据才会显示。通过调试,我可以看到数据被正确加载到数组中,因此我确信这是一个
UITableViewController
UITableViewCell
问题

除了显而易见的
self.myTableView.reloadData
调用reloadData这两种最常见的方法外,我还尝试了这里讨论的StackOverflow的各种解决方案,如下所示:

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

dispatch_async(dispatch_get_main_queue(), ^{
    [self.myTableView reloadData];});
}
每次我试图从ArticlesTableViewController实例中调用这些,都没有成功

2) 第二个问题 DateLabel仅在打开应用程序时显示在第一个单元格中,然后DateLabel显示在其余单元格中,我实际上必须向下滚动,然后再向上滚动。从上方返回视图的单元格包含日期标签,但如果从下方返回视图的单元格再次消失。相当混乱的东西

这是我的相关代码

cellforrowatinexpath
(在
文章StableViewController
中):

自定义单元格代码(对于
ArticleStableWicell
):

编辑 下面是
分类表视图控制器
中的
单元格行索引路径
代码(第一个表):

下面是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;
}

您说您有两个UITableView,但我看不出您的代码将它们区分开来。每个UItableview都应该有自己的出口。我已经用相关代码更新了我的帖子。在同一个
视图控制器中是否有两个
-(UITableViewCell*)tableView:(UItableview*))tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
?这是行不通的,操作系统如何知道哪一个与我编辑过的表相关?为了清楚起见,这些代码段属于单独的TableViewController类。好吧,如果您使用的是UITableViewController而不是UITableView,然后UITableViewController负责每个tableView的数据源和委托,而不是UIViewController。因此,任何重新加载数据源的调用(即重新加载UITableView的数据)都应该在UITableViewController中进行,而不是在UIViewControllerI中进行相应的更改。谢谢你能谈谈你对IVAR的第一次评论吗?我做了正确的更改了吗?不要使用
self.myTableView
尽可能使用
tableView
(例如在
cellforrowatinexpath:
- (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;
   }
- (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;
}