3

これにはたくさんの質問があるようですが、他の人の回答を使用することはできないので、誰かが私がこれをどのように行っているかを確認できることを望んでいました. 使おうとしています。私は 2 つのカスタム UITableViewCells を持っていますが、それらには現在 BOOL プロパティがあり、それがスタイリングの邪魔になっています。

cellForRowAtIndexPath返されるデータの種類に基づいたメソッド内で、セルのスタイルを設定しています。データが「月」ヘッダーである場合は、細長く見えるセルであり、「ニュース項目」である場合は、より大きな白いセルになります。

ここに画像の説明を入力

テーブルが読み込まれるとすべてがうまく見えますが、下にスクロールしてさらにセルを作成してから上にスクロールすると、セルが再作成され、最終的にメモリが不足しているためスクロールが遅くなります。

ブレークポイントを設定すると、dequeueReusableCellWithIdentifier常に nil が返されるため、セルが再利用されることはありません。これは問題のようです。

この図では、セルが互いに積み重なってめちゃくちゃになっていることがわかります。

ここに画像の説明を入力

ここに私のコード:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *NewsCellIdentifer = @"NewsCellIdentifier";
    static NSString *MonthCellIdentifier = @"MonthCellIdentifier";


    NSUInteger row = [indexPath row];
    NewsItem *item = [self.newsArray objectAtIndex:row];

    if (item.IsMonth == YES)
    {
        NewsMonthUITableViewCell *cell = [self.mytableView dequeueReusableCellWithIdentifier:MonthCellIdentifier];

        if (cell == nil)
        {
            cell = [[NewsMonthUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MonthCellIdentifier];
        }

        // This handles any other "date" cells to allow for different spacing styles.
        if (item.IsMonth)
        {
            UIImageView *av = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 400, 20)];
            av.backgroundColor = [UIColor clearColor];
            av.opaque = NO;
            av.image = [UIImage imageNamed:@"month-bar-bkgd.png"];
            UILabel *monthTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 150, 20)];;
            CGFloat font = 11.0f;
            monthTextLabel.font = [BVFont HelveticaNeue:&font];
            monthTextLabel.backgroundColor = [UIColor clearColor];
            monthTextLabel.font = [BVFont HelveticaNeue:&font];
            monthTextLabel.textColor = [BVFont WebGrey];
            monthTextLabel.text = item.Title;

            cell.backgroundColor = [UIColor clearColor];
            [cell.contentView addSubview:av];
            [cell.contentView addSubview:monthTextLabel];
        }

        return cell;

    }
    else
    {
        NewsUITableViewCell *cell = [self.mytableView dequeueReusableCellWithIdentifier:NewsCellIdentifer];

        if (cell == nil)
        {
            cell = [[NewsUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer];
        }

        cell.contentView.backgroundColor = [UIColor clearColor];

        UIView *whiteRoundedCornerView = [[UIView alloc] initWithFrame:CGRectMake(10,10,300,100)];
        whiteRoundedCornerView.backgroundColor = [UIColor whiteColor];
        whiteRoundedCornerView.layer.masksToBounds = NO;
        whiteRoundedCornerView.layer.cornerRadius = 3.0;
        whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(-1, 1);
        whiteRoundedCornerView.layer.shadowOpacity = 0.5;

        [cell.contentView addSubview:whiteRoundedCornerView];
        [cell.contentView sendSubviewToBack:whiteRoundedCornerView];
        [cell.contentView addSubview:[self NewsItemThumbnailView:item]];
        [cell.contentView addSubview:[self NewsItemTextView:item]];
        [cell.contentView addSubview:[self NewsItemCornerIconIndicatorView:item]];

        return cell;

    }

    return nil;

}

助けやアドバイスをありがとう!

4

4 に答える 4

2

動的プロトタイプなしでストーリーボードを使用しているため、ブロック内にサブビューを作成および追加するコードを配置する必要がありますif (cell==nil)。そうしないと、テーブルビュー セルが再利用されるたびに、すべてのサブビューが再度追加されます。

今後は、動的プロトタイプ (サブクラス化された UITableViewCells を使用) で Storyboards を使用し、IB のセルでカスタマイズを行うことをお勧めします。

于 2013-02-28T00:26:48.033 に答える
1

興味深い問題です。セルのデキューが nil を返していると言いました。これはブレークポイントまたはログで確認されていますか? それとも、これはあなたが投稿した画像からの単なる推測ですか?

セルが互いに重なり合って再利用されないという問題には、別の原因があるように思えます。

セルをスクロールするたびに、whiteRoundedCornerView が作成され、セルに追加されていることがわかります。これが問題の原因ではない場合でも、問題であることは間違いありません。セルを正しく作成していません。このコードを if (cell == nil) ブロックに入れる必要があります。実際、ブロックの外側にあるほとんどすべてのコードは、ブロックに入る必要があります。次に、テキストまたは画像の値を設定するすべてのコードをブロックの外に出す必要があります。誰かがすでにこの提案をしているようですが、あなたは満足していません。それはまだ間違っているので、アプリを修正したい場合はこれを修正する必要があることをもう一度強調します。(ちなみに見栄えの良いアプリ)。

また、あなたのコードの他の側面について提案をすることができれば. ヘッダーをカスタム コーディングし、実際のセクション ヘッダーを使用しませんでした。これは私にとって非常に奇妙です。また、冗長な「if (item.isMonth)」があります。1つはすでに別のブロックにあるため、常に月のアイテムになります。

于 2013-02-27T17:32:38.597 に答える
1

cast your cells to Customcells,and use only tableView see below example.

   NewsMonthUITableViewCell *cell = (NewsMonthUITableViewCell *)[tableView dequeueReusableCellWithIdentifier:MonthCellIdentifier];
  NewsUITableViewCell *cell =(NewsUITableViewCell*) [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer];

Use dynamic prototype cells , for prototype cells there is no requirement of cell allocation & check for proper cellIdentifier.

on storyboard create two prototype cells & give them different cellIdentifier, in your case NewsCellIdentifer & MonthCellIdentifier. be sure for the spelling of NewsCellIdentifer because you have missed i from NewsCellIdentifer.

于 2013-02-27T16:57:21.013 に答える
0

iOS 7 とストーリーボードで同じ問題が発生しましたが、Xcode-SDK の古いバージョンでは同じコードでこの問題が発生したことはなく、stackoverflow から多くの提案を試みましたが、修正できませんでした。Apple のTableView Programming Guideには、よく説明されたガイドがあります。を使用する必要さえありませんcell==nil

だから私はそれが他の人を助けることを願ってここに指示を出します:

適切に再利用されるストーリーボードを使用してカスタム テーブルビュー セルを作成するには、2 つの異なるアプローチを取ることができます。私は個人的にはより簡単な最初の方法を好みますが、ここでは両方のソリューションを紹介します。

最初のアプローチ

  1. マスター/ディテール アプリケーション テンプレートを使用してプロジェクトを作成し、[ストーリーボードを使用] オプションを選択します。
  2. ストーリーボード キャンバスで、マスター ビュー コントローラーを選択します。
  3. Identity インスペクタで、Class がカスタム MasterViewController クラスに設定されていることを確認します。
  4. マスター ビュー コントローラー内のテーブル ビューを選択します。
  5. 属性インスペクターで、コンテンツポップアップメニューが動的プロトタイプに設定されていることを確認します。
  6. プロトタイプ セルを選択します。
  7. 属性インスペクタで、スタイルポップアップメニューから「カスタム」を選択します。
  8. [識別子] テキスト フィールドに再利用識別子を入力します。dequeueReusableCellWithIdentifier:これは、メッセージでテーブル ビューに送信する再利用識別子と同じです。
  9. [アクセサリ] ポップアップ メニューで [ディスクロージャー インジケータ] を選択します。
  10. オブジェクトをライブラリからセルにドラッグします。この例では、2 つのラベル オブジェクトをドラッグし、セルの端近くに配置します (アクセサリ ビュー用のスペースを残します)。
  11. オブジェクトを選択し、その属性、サイズ、自動サイズ変更特性を設定します。

このプロシージャのプログラム部分に設定する重要な属性は、各オブジェクトのtagプロパティです。Viewのセクションでこのプロパティを見つけて、Attributes inspector各オブジェクトに一意の整数を割り当てます。

ここで、テーブル ビューのデータを取得するために通常記述するコードを記述します。(この例では、必要なデータは各セルの行番号だけです。) データ ソース メソッド tableView:cellForRowAtIndexPath: を実装して、プロトタイプから新しいセルを作成し、次のコードと同様の方法でデータを入力します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

    UILabel *label;

    label = (UILabel *)[cell viewWithTag:1];
    label.text = [NSString stringWithFormat:@"%d", indexPath.row];

    label = (UILabel *)[cell viewWithTag:2];
    label.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row];

    return cell;
}

このコードには、注意すべき点がいくつかあります。

  • プロトタイプ セルに割り当てる文字列識別子は、 でテーブル ビューに渡す文字列と同じですdequeueReusableCellWithIdentifier:
  • プロトタイプ セルはストーリーボードで定義されているため、このdequeueReusableCellWithIdentifier:メソッドは常に有効なセルを返します。戻り値を nil と照合して手動でセルを作成する必要はありません。
  • このコードは、 を呼び出してセル内のラベルを取得viewWithTag:し、タグの整数を渡します。次に、ラベルのテキスト コンテンツを設定できます。

第二のアプローチ

タグを使用したくない場合は、別の方法を使用してセル内のコンテンツを設定できます。設定するオブジェクトのアウトレット プロパティを持つカスタムUITableViewCellサブクラスを定義します。ストーリーボードで、新しいクラスをプロトタイプ セルに関連付け、アウトレットをセル内の対応するオブジェクトに接続します。

カスタム セル コンテンツにアウトレットを使用するには

  1. MyTableViewCell という名前の Objective-C クラスをプロジェクトに追加します。
  2. のインターフェイスに次のコードを追加しますMyTableViewCell.h

    @interface MyTableViewCell : UITableViewCell

    @property (非アトミック、弱い) IBOutlet UILabel *firstLabel; @property (非アトミック、弱い) IBOutlet UILabel *secondLabel; @終わり

  3. の実装に次のコードを追加しますMyTableViewCell.m

    @synthesize firstLabel, secondLabel;

  4. データ ソースを実装するソース ファイルに次のコード行を追加します。

    #import "MyTableViewCell.h"

  5. を使用しIdentity inspectorて、プロトタイプ セルのクラスを に設定しMyTableViewCellます。

  6. 接続インスペクタを使用して、プロトタイプ セルの 2 つのアウトレットを対応するラベルに接続します。 ここに画像の説明を入力

  7. データ ソース メソッドを実装するtableView:cellForRowAtIndexPath:

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
    
    cell.firstLabel.text = [NSString stringWithFormat:@"%d", indexPath.row];
    cell.secondLabel.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row];
    
    return cell;
    }
    

このコードは、アクセサー メソッドを使用してセル内のラベルにアクセスします (ここではドット表記を使用します)。その後、コードでラベルのテキスト コンテンツを設定できます。

于 2013-11-19T18:55:58.843 に答える