0

で動的な値を使用すると、パフォーマンスの問題が発生しますheightForRowAtIndexPath: (静的な値を設定すると応答性が大幅に向上するため、この方法であることはわかっています)。私のテーブルには約 3000 個のセルが含まれています。

動的な値を使用するとパフォーマンスが低下する理由は理解できますが (主に、データを表示する前に、メソッドの計算をテーブル内のセルごとに 1 回実行する必要があるため)、より効率的にする方法がわかりません。 .

私が遭遇した同様の質問の多くで、提案された解決策は、NSStringsizeWithFontメソッドを使用しheightForRowAtIndexPath:て高速化することでした。私は現在それを行っていますが、テーブルのロードにはまだ約1.5秒かかります(およびリロードは、やや頻繁に行われます)。これは長すぎるため、最適化する必要があります。

私が現在使用しているコード (少なくともその本質) は以下のとおりです。

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

    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        label = [[UILabel alloc] initWithFrame:CGRectZero];
        // set up label..
        [[cell contentView] addSubview:label];

    }

    NSDictionary *dict = alphabetDict; //dictionary of alphabet letters (A-Z). each key contains an NSArray as its object
    CGFloat rightMargin = 50.f; //padding for the tableview's index titles

    NSString *key = [[[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section];
    NSArray *array = [dict objectForKey:key];
    NSString *cellText = [array objectAtIndex:indexPath.row];

    //TABLE_WIDTH is 268.f, CELL_MARGIN is 14.f
    CGSize constraintSize = CGSizeMake(TABLE_WIDTH - (CELL_MARGIN * 2) - rightMargin, 20000.0f);
    CGSize labelSize = [cellText sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
    [label setFrame:CGRectMake(CELL_MARGIN, CELL_MARGIN, TABLE_WIDTH - (CELL_MARGIN * 2) - rightMargin, labelSize.height)];
    [label setText:cellText];

    return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //TODO make this faster

    NSDictionary *dict = alphabetDict;
    CGFloat rightMargin = 50.f;

    NSString *key = [[[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section];
    NSArray *array = [dict objectForKey:key];
    NSString *cellText = [array objectAtIndex:indexPath.row];

    CGSize constraintSize = CGSizeMake(TABLE_WIDTH - (CELL_MARGIN * 2) - rightMargin, 20000.0f);
    CGSize labelSize = [cellText sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    return labelSize.height + (CELL_MARGIN * 2) + 16.f;  
}

このコードをさらに合理化するために、誰かが私を正しい方向に向けることができますか? ありがとう!

4

3 に答える 3

5

私は以前にこのような状況に直面したことがあります。私の解決策は、すべての計算を行い、[tableView reloadData] を実行する前に、heightsArray と呼ばれる NSMutableArray に高さを格納することです。それで

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
   [heightsArray objectAtIndex:indexpath.row];
}

上下スクロール中は計算なし。配列からの単純な読み取り。計算が前もって行われるため、最初のホールドアップはより大きくなりますが、スクロール中のパフォーマンスの向上という点では価値があります。バックグラウンド スレッドで計算を実行することもできるため、処理時間を節約できます。バックグラウンドスレッドで呼び出すことができるメソッドですべてを実行し、高さの配列を準備します。

于 2012-08-27T18:07:56.543 に答える
1

で最も時間がかかる部分heightForRowAtIndexPathは次のとおりです。

[[[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section];

したがって、プロパティsortedKeysを追加することから始めて、次のように使用できます。

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *key = [sortedKeys objectAtIndex:indexPath.section];
    CGFloat rightMargin = 50.f;
    // ...
}
于 2012-08-27T16:24:48.393 に答える
0

crypticcoder には良い提案があります。より柔軟で、テーブルの変更 (挿入、削除、並べ替え) をサポートするバリエーションをお勧めします。

UITableViewCell のサブクラスであるクラスを作成し、それに cellHeight プロパティと ivar cellHeight_ を追加します。次のように合成します。

@synthesize cellHeight=cellHeight_;

クラス内で次のコードを使用して、セルの高さを遅延計算します。

-(CGFloat) cellHeight{
    if (cellHeight_ != 0)
        return cellHeight_;
    else {
        NSDictionary *dict = alphabetDict;
        CGFloat rightMargin = 50.f;

        NSString *key = [[[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section];
        NSArray *array = [dict objectForKey:key];
        NSString *cellText = [array objectAtIndex:indexPath.row];

        CGSize constraintSize = CGSizeMake(TABLE_WIDTH - (CELL_MARGIN * 2) - rightMargin, 20000.0f);
        CGSize labelSize = [cellText sizeWithFont:[UIFont systemFontOfSize:17] constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

        cellHeight_ = labelSize.height + (CELL_MARGIN * 2) + 16.f; 
        return cellHeight_; 
    }
}

sch のように、私はそこに並べ替えが好きではありませんが、それが実際にパフォーマンスの問題でない場合は、そのままにしておきます。

セルの内容を変更したい場合は、 cellHeight_ をゼロにリセットして、(再び必要になったときに) 遅延再計算されるようにしてください。

于 2012-08-27T18:31:02.273 に答える