55

我正在尝试在单元格中加载解析的数据,但问题是它是同步发生的,并且 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;


}
4

8 回答 8

130

成功加载数据后将其放在某处:

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

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

此代码使用 Apple 的 GCD 技术强制 reload data 函数在主线程上运行。阅读更多关于 并发编程指南以获得更多理解(它是一个相当大的领域,因此很难在评论中解释)无论如何,如果你不太了解它不是很推荐,因为它会导致程序在一些罕见的情况下崩溃。

于 2013-06-18T10:03:30.923 回答
16

对于迅捷3:

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

对于快速 2:

dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.reloadData()
            })
于 2016-03-29T22:01:28.063 回答
9

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

[tableView reloadData];

由于这是同步发生的,因此您可能应该具有类似的功能

-(void) updateTable
{
    [tableView reloadData];
}

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

[self performSelectorOnMainThread:@selector(updateTable) withObject:nil waitUntilDone:NO];
于 2012-06-04T17:17:45.180 回答
4

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

dispatch_async(dispatch_get_main_queue(), ^{
            [cell setNeedsDisplay];
            [cell.contentView addSubview:yourView];
        });
于 2015-05-19T08:55:02.473 回答
2

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

我正在使用静态单元格并且 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) {

            }];
        }];
}
于 2016-03-15T10:12:38.507 回答
1

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

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

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

- (void)viewWillAppear {
    [tableView reloadData];
}
于 2014-11-19T19:59:43.477 回答
0

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

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

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

于 2016-10-14T00:03:48.793 回答
0

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

在 tableView 本身上设置estimatedHeight,或者从estimatedHeightForRowAt你的 UITableViewDelegate 中返回一个估计值。

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

于 2020-06-15T08:51:37.817 回答