2009-07-03 10 views
0

私はネットからいくつかの情報を取得するスレッド化されたUITableViewを書いていました。画像がロードされている間、通常のcell.imageの代わりにアクティビティインジケータを表示したいと思います。どのようにUITableViewCellでサブビューの位置を変更しますか?

カスタムラベルとアクティビティインジケータが正しく動作しないという問題があります。ラベルは適切な位置に開始され、アクティビティインジケータが適切な位置に表示され、アニメーション化されますが、画像ダウンロードスレッドで最初のコールバックが発生すると(基本的に1つの画像のみが読み込まれます)、ビュー全体1つの参照があるかのようにリセットして、それらのフレームをすべてリセットしていました...

私はオーバーロードされました - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;問題の

コードはここにある:iphoneアプリケーション開発への新たな

// Set up the cell... 
    if(![[cell contentView] viewWithTag:indexPath.row+200]){ 
     UILabel *newLabel = [[UILabel alloc] init]; 
     newLabel.text = [[personList objectAtIndex:indexPath.row] name]; 
     newLabel.frame = [[cell contentView] frame]; 
     [[cell contentView] addSubview:newLabel]; 
     newLabel.tag = indexPath.row+200; 
     [newLabel release]; 
    } 
    else{ 
     UILabel *alreadySetLabel = (UILabel *)[[cell contentView] viewWithTag:indexPath.row+200]; 
     alreadySetLabel.text = [[personList objectAtIndex:indexPath.row] name]; 
     alreadySetLabel.frame = [[cell contentView] frame]; 
    } 

    UIImageView *tmpImageView = cell.imageView; 

    NSLog(@"In cell name: %@", [[personList objectAtIndex:indexPath.row] name]); 
    NSLog(@"In cell profile image: %@", [[personList objectAtIndex:indexPath.row] profileImage]); 

    if([[personList objectAtIndex:indexPath.row] profileImage]){ 
     tmpImageView.image = [[personList objectAtIndex:indexPath.row] profileImage]; 
     [[[cell contentView] viewWithTag:indexPath.row+100] removeFromSuperview]; 
     UILabel *labelRef1 = (UILabel *)[[cell contentView] viewWithTag:indexPath.row+200]; 
     [labelRef1 setFrame:CGRectMake(cell.contentView.frame.origin.x+70, cell.contentView.frame.origin.y, labelRef1.frame.size.width, labelRef1.frame.size.height)]; 
    } 
    else{ 
     NSLog(@"%@", [[personList objectAtIndex:indexPath.row] imageFilePath]); 
     if(![[cell contentView] viewWithTag:indexPath.row+100] && [[personList objectAtIndex:indexPath.row] imageFilePath]){ 
      UIActivityIndicatorView *newSpin = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
      [newSpin setTag:indexPath.row+100]; 
      [newSpin startAnimating]; 
      [newSpin setFrame:CGRectMake(5, ((cell.contentView.frame.size.height/2)-7), 30, ((cell.contentView.frame.size.height/2)-7)+15) ]; 
      [[cell contentView] addSubview:newSpin]; 
      [newSpin release]; 
      UILabel *labelRef2 = (UILabel *)[cell viewWithTag:indexPath.row+200]; 
      [labelRef2 setFrame:CGRectMake(cell.contentView.frame.origin.x+70, cell.contentView.frame.origin.y, labelRef2.frame.size.width, labelRef2.frame.size.height)]; 
     } 
    } 

ブランド、2週間以内に、私はタグの使用を誤解していた場合、私は思ったんだけど?タグ値をindexPathにリンクすることができたら、カスタムビューを参照する一意の識別子を思いつくことができますか? 100と200は任意の値であり、私は誤って1つの画面の中でタグを再利用しないようにしています - 必要があるかどうかわからないので、タグはサブビューを通してのみ検索されると考えました。

アドバイスを事前にいただきありがとうございます。

おかげで、 ジョシュ...これは、よりエレガントにする方法についての一般的なヒントにもオープン

私は、単一の基準があったかのように正確にあなたが望むすべてリセット」によって何を意味するかわからないんだけど

答えて

1

と私はそれらのすべてのフレームをリセットしていた "しかし、私はいくつかのことをwrtを指摘させてください。タグの使用、および一般的なテーブルビューのセル画像のロード。

タグ ビュー内のサブビューを取得/識別するだけの方法です - 彼らはグローバル一意である必要はありません。実際には、indexPath.rowをタグ値に組み込むのは良いことではありません。なぜなら、テーブルビューのセルはに再利用されるからです(間違いなくdequeueReusableCellWithIdentifier:を使用する限り)。さらに、タグ値を定数(例:#define)として定義し、コード内の定数のみを参照します。こうすることで、コードの記述性が向上し、エラーが発生しなくなり、メンテナンス性が向上します。

正直言って、私はタグを全く使っていないのです。証書の中で、tableView:cellForRowAtIndexPath:の "オンザフライ"でテーブルビューセルを構築することは、私が出会った唯一のシナリオです(名前付きアウトレットがないため、選択肢がありません)。タグをつぶすのではなく、UITableViewCellをサブクラス化することをお勧めします。実際には大したことではありませんが、コードははるかに洗練され、そのクラス内のすべてのセルに関連するものを簡単にカプセル化できます。ネットワーク上でテーブルビューのセルイメージを非同期に読み込むなど、

について非同期画像読み込みものについては、this project on githubをご覧ください。基本的には、画像を非同期的にロード(フリック)し、読み込みが完了したときにテーブルビューでそれらを更新する方法をデモンストレーションするデモプロジェクトです。完璧な実装ではありませんが、少なくとも良い出発点です。私は最近同じことをしましたが、私のアプローチはサブクラスUIImageViewで、このサブクラスですべての非同期ロード/更新を行いました。主な理由は、一般的で再利用可能なソリューションがほしいということでした。

0

あなたは右のサブクラス化は、カプセル化とコードの量まで行く方法でした。私はそれを変更する必要があります。

補足として、もう1つのコードブランチで問題を解決しました。

明らかに、問題は、サブビューに追加したカスタムラベルが、テーブルがreloadDataになるたびにフレームをリセットしていたことです。アクティビティインジケータまたは読み込まれた画像のためのスペースを確保するために、70ピクセル以上移動していることがわかります。これは、最初にスルーし、origin.x = 0にリセットすると、追加の画像がバックグラウンドスレッドにロードされなくなったときにリセットされます。

明らかに、ラベルフレームは何とか​​リセットされますか?私のコードは、rectの静的な長さを保つという印象を受けていたので、100のタグを持つセルcontentViewのサブビューを検出しました(あなたが提案したように静的な値に変更しました)ビューが存在するように。これは当てはまりません。既に存在するかどうかに関係なく、フレームを明示的に設定しなければなりませんでした。とにかく、おそらくちょうどボンネットの下で起こっていることを完全に理解していない。 elseにsetFrameを追加すると、すべてうまく動作しました。

ありがとう、 Josh

関連する問題