2

に表示するために SQLite データベースからデータを読み込んでいますUITableView。ユーザーがブロックされず、テーブルがすばやく表示されるようにするために、キューを作成し、バックグラウンドで実行されるデータベース操作を追加しています。

追加は良好で正常に動作しますが、何らかの理由でランダムに一部の行がデータで更新されません!

行をクリックするとデータが更新されるため、データが正しく設定されていることはわかっていますが、UI を更新する方法が見つからないようです。使用などを含めてすべて試しましsetNeedDisplayたが、何も機能しません!

これが私のコードです:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell* cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.textLabel.textAlignment = UITextAlignmentRight;
        cell.textLabel.numberOfLines = 0;
        cell.textLabel.font = [UIFont systemFontOfSize:14];
    }

    cell.accessoryType = UITableViewCellAccessoryNone;
    cell.textLabel.text = @"Loading ...";
    cell.tag = indexPath.row;

    NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self 
                                                                     selector:@selector(setCellData:) 
                                                                       object:cell];

    [queue addOperation:op];
    [op release];

    return cell;
}


- (void) setCellData:(UITableViewCell *)cell{

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    sqlite3_stmt            *statement2;

    NSString *sqlStr = [NSString stringWithFormat:@"SELECT * FROM poemdata WHERE catid='%d' GROUP BY poemid LIMIT 1 OFFSET %d",catId,cell.tag];
//  NSLog(@"%@",sqlStr);
    sqlite3_prepare_v2(database, [sqlStr cStringUsingEncoding:NSASCIIStringEncoding], -1, &statement2, nil);

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    if(sqlite3_step(statement2) == SQLITE_ROW){
        cell.textLabel.text = [[NSString alloc] initWithUTF8String: (char *)sqlite3_column_text(statement2, 3)];
        cell.tag = sqlite3_column_int(statement2, 6);
    }else{
        cell.textLabel.text = @"Error";
    }
    sqlite3_finalize(statement2);

    [pool release];
}
4

2 に答える 2

4

あなたのロジックには欠陥があり、すでに経験している問題だけでなく、ひどいパフォーマンスも経験すると思います。すべてのデータまたはデータの少なくとも一部をロードする全体的なオペレーションを起動し、終了時にテーブルをリロードするように要求する方がよいでしょう。

現在行っている方法は、すべてのセルがデータベースにヒットし、1 つの行を選択し、このデータをどこにもキャッシュしないことです (つまり、ビューからスクロールして戻ってきた場合、データベースに再度ヒットする必要があります)。さらに、操作が終了したときにこのセルで呼び出される描画コードはありません (これが、クリックして描画呼び出しが発生するまで表示されない理由です)。

このすべてのデータをカスタム オブジェクトの配列にロードする必要があります。ロードしたら、テーブルをリロードし、新しく入力された配列を使用してセルにプロパティを設定する必要があります。

于 2011-03-17T18:07:23.447 に答える
1

バックグラウンド スレッドからユーザー インターフェイスを更新していますが、これは誤りです。すべてのユーザー インターフェイス作業は、メイン スレッドで実行する必要があります。バックグラウンドスレッドcellからのデータをNSDictionary.

performSelectorOnMainThread:withObject:waitUntilDone:を参照してください。Apple の Threading Programming Guide のThreads and Your User Interface もお読みください。

@theChrisKent はパフォーマンスについて良い点を指摘しましたが、このスレッドの問題が不規則な動作の原因である可能性が高くなります。

于 2011-03-17T19:36:01.460 に答える