在我滚动之前,数据不会加载到 UITableView 中

Posted

技术标签:

【中文标题】在我滚动之前,数据不会加载到 UITableView 中【英文标题】:Data doesn't load in UITableView until I scroll 【发布时间】:2012-06-08 18:14:35 【问题描述】:

我正在尝试在单元格中加载已解析的数据,但问题是它是同步发生的,并且 UitableView 在数据完成加载之前不会显示。我试图通过使用 performSelectorInBackground 来解决这个问题,但现在数据不会加载到单元格中,直到我开始滚动。这是我的代码:

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    [self performSelectorInBackground:@selector(fethchData) withObject:nil];





- (void)viewDidUnload

    [super viewDidUnload];
    // Release any retained subviews of the main view.
self.listData = nil;
    self.plot=nil;



-(void) fethchData


    NSError *error = nil;
    NSURL *url=[[NSURL alloc] initWithString:@"http://www.website.com/"];
    NSString *strin=[[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

    htmlParser *parser = [[HTMLParser alloc] initWithString:strin error:&error];

    if (error) 
        NSLog(@"Error: %@", error);
        return;
    

    listData =[[NSMutableArray alloc] init];
    plot=[[NSMutableArray alloc] init];

    HTMLNode *bodyNode = [parser body];
    NSArray *contentNodes = [bodyNode findChildTags:@"p"];


    for (HTMLNode *inputNode in contentNodes) 
            [plot addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];    
        


    NSArray *divNodes = [bodyNode findChildTags:@"h2"];

    for (HTMLNode *inputNode in divNodes) 

            [listData addObject:[[inputNode allContents] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];          

        
    


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 


    static NSString *CellIdentifier = @"Cell";
    //here you check for PreCreated cell.
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    

    //Fill the cells...  


    cell.textLabel.text = [listData objectAtIndex:indexPath.row];
    cell.textLabel.font = [UIFont boldSystemFontOfSize:14];
    cell.textLabel.numberOfLines=6; 
    cell.textLabel.textColor=[UIColor colorWithHue:0.7 saturation:1 brightness:0.4 alpha:1];


    cell.detailTextLabel.text=[plot objectAtIndex:indexPath.row];
    cell.detailTextLabel.font=[UIFont systemFontOfSize:11];
    cell.detailTextLabel.numberOfLines=6;

    return cell;



【问题讨论】:

只加载可见单元格,其余单元格在滚动后出现后加载。 【参考方案1】:

把这个放在数据加载成功后

dispatch_async(dispatch_get_main_queue(), ^
    [self.tableView reloadData];
);

这解决了在您不在主线程中时调用 GUI 更新的问题。

此代码使用 Apple 的 GCD 技术强制重新加载数据函数在主线程上运行。阅读更多关于 Concurrency Programming Guide 更多理解(这是相当大的领域,所以很难在评论中解释) 不管怎样,如果不是很了解,不太推荐,因为它会导致程序在一些罕见的情况下崩溃。

【讨论】:

谢谢。我匆忙移动了一些东西,并没有意识到我的数据加载是在另一个线程中,因此我的 reloadData 也是如此。谢谢你帮我回去分析。 谢谢!这只是解决了我遇到的一个非常烦人的错误。 @Envil 你能否解释一下它是如何导致崩溃的。我的应用程序随机崩溃。即使花了很多时间调试,我也无法修复崩溃。 @AbdurrahmanMubeenAli 你应该创建一个新问题并彻底描述它。我不能用你的小描述给你一个解决方案。 @Envil 在你的回答中,你说,“......它会导致程序崩溃......”。我只是想知道你知道的崩溃案例。【参考方案2】:

对于 Swift 3:

DispatchQueue.main.async(execute:  () -> Void in
                self.tableView.reloadData()
            )

对于 swift 2:

dispatch_async(dispatch_get_main_queue(),  () -> Void in
                self.tableView.reloadData()
            )

【讨论】:

【参考方案3】:

您真正需要做的就是随时更新后端数据,致电

[tableView reloadData];

由于这是同步发生的,你应该有一个类似的函数

-(void) updateTable

    [tableView reloadData];

在您的下载调用中添加数据后

[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:NO];

【讨论】:

它说“未知的接收者tableView” 代码仅作为示例,我不知道您的类或视图布局的确切结构。关键是,您需要获取对表视图的引用(如果您的类是 UITableViewController 的实例或子类,则应该只有 self.tableView)并在其上调用 reloadData 方法 在 UITabbleviewController 中它将是 self.tableView 现在好多了,但我仍然需要触摸 tableView 才能加载数据。以前,我不得不滚动更多。无论如何,谢谢你们。 我用这个 [self performSelector:@selector(fethchData) withObject:nil afterDelay:0];结合您的示例代码。【参考方案4】:

U 可以使用 [cell setNeedsDisplay]; 例如:

dispatch_async(dispatch_get_main_queue(), ^
            [cell setNeedsDisplay];
            [cell.contentView addSubview:yourView];
        );

【讨论】:

【参考方案5】:

我遇到了这个问题,我整天都在处理它。

我正在使用静态单元格并且 reloadData 导致错误加载,它仅显示可见单元格并删除其他单元格。 我注意到的是,当我向下滚动(y 为负值)时,单元格正确加载,所以我编写了这段代码并且它工作了,即使我不喜欢这样。

如果您找到更好的解决方案,请拍摄。

-(void)reloadTableView
        CGPoint point = self.tableSettings.tableView.contentOffset;
        [self.tableSettings.tableView reloadData];

        [UIView animateWithDuration:.001f animations:^
            [self.tableSettings.tableView setContentOffset:CGPointMake(point.x, -10)];
         completion:^(BOOL finished) 
            [UIView animateWithDuration:.001f animations:^
                [self.tableSettings.tableView setContentOffset:point];
             completion:^(BOOL finished) 

            ];
        ];

【讨论】:

这对我有用。如果您发现实际问题,请告诉我【参考方案6】:

我遇到了完全相同的问题!我希望 UITableView 在视图控制器出现之前被完全填充。 Envil 的帖子为我提供了所需的信息,但我的解决方案最终有所不同。

这就是我所做的(经过改造以适应提问者的上下文)。

- (void)viewDidLoad 
    [super viewDidLoad];
    [self performSelectorInBackground:@selector(fethchData) withObject:nil];


- (void)viewWillAppear 
    [tableView reloadData];

【讨论】:

【参考方案7】:

首先,这半解决了我的相关问题。我想在表格单元格中圆角图像。异步调度解决了一些但不是所有图像的问题。有任何想法吗?

其次,我认为您应该通过使用这样的闭包捕获列表来避免创建强引用循环:

DispatchQueue.main.async(execute:  [weak weakSelf = self] () -> Void in
            weakSelf!.tableView.reloadData()
        )

见:https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097-CH20-ID52

【讨论】:

这解决了我的问题: DispatchQueue.main.async(execute: [weak weakCell = cell] () -> Void in weakCell!.imageView!.layer.cornerRadius = cell.imageView!.frame .width/4.0 weakCell!.imageView!.clipsToBounds = true )【参考方案8】:

我在使用自定尺寸单元格时遇到了同样的问题,我发现将estimatedHeight 设置为 50 可以解决问题。

在 tableView 本身上设置estimatedHeight 或从您的 UITableViewDelegate 中的estimatedHeightForRowAt 返回估计值。

只要估计值大于 0,它似乎就可以工作。

【讨论】:

以上是关于在我滚动之前,数据不会加载到 UITableView 中的主要内容,如果未能解决你的问题,请参考以下文章

具有动态数据初始化的 UiTableviewCell 未正确加载

UITableView 布局在滚动之前不会刷新

UIImageView 在滚动之前不会加载到 UITableViewCell 中

在我旋转屏幕之前,LiveData 不会加载到片段中

除非滚动,否则 UICollectionViewCells 不会加载

UITableView 在使用 Swift 中的 Master Detail App 滚动之前不会重新加载