web-dev-qa-db-ja.com

スクロールするまでUITableViewにデータが読み込まれません

解析したデータをセルにロードしようとしていますが、問題は同期的に発生しており、データのロードが完了するまで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;


}
52
Benjamen

データが正常にロードされた後、これをどこかに配置します

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

これにより、メインスレッドにいないときにGUIアップデートを呼び出す問題が修正されます。

このコードは、AppleからのGCDテクノロジーを使用して、データ再ロード機能をメインスレッドで強制的に実行します。詳細については、 同時実行プログラミングガイド を参照してください。 (非常に大きなフィールドなので、コメントで説明するのは困難です)とにかく、プログラムがまれにクラッシュする可能性があるため、よく理解していない場合はあまりお勧めできません。

129
Envil

Swift 3:の場合

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

Swift 2:の場合

dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.reloadData()
            })
14
Hamid

本当に必要なのは、バックエンドデータの更新があるときはいつでも、

[tableView reloadData];

これは同期的に行われているため、おそらく次のような関数が必要です。

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

ダウンロード呼び出しにデータを追加した後

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

Uは[cell setNeedsDisplay]を使用できます。例えば:

dispatch_async(dispatch_get_main_queue(), ^{
            [cell setNeedsDisplay];
            [cell.contentView addSubview:yourView];
        });
2
Devashis Kant

私はこの問題を抱えていて、一日中それを扱っていました。

私は静的セルを使用していますが、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) {

            }];
        }];
}
1
Arben Pnishi

私はまったく同じ問題を抱えていました! View Controllerが表示される前に、UITableViewを完全に設定する必要がありました。 Envilの投稿は私に必要な情報を与えてくれましたが、私の解決策は異なっていました。

これが私がしたことです(質問者のコンテキストに合うように改造されました)。

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

- (void)viewWillAppear {
    [tableView reloadData];
}
1
Jeremy Herrero

まず、これは私の関連する問題を半解決しました。テーブルセル内の画像の角を丸くしたい。非同期的にディスパッチすると、すべてではないが一部の画像の問題が修正されました。何か案は?

第二に、次のようなクロージャーキャプチャリストを使用することで、強力な参照サイクルの作成を回避することになっていると思います。

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

0
user3590685