0

ArrayControllerBindingsを使用して、カスタム セルでNSTableViewをセットアップしようとしています。これを実現するために、カスタム セルにサブビューを追加しました。データ接続は何とか機能しているようです。ただし、修正できない再描画の問題があるようです。アプリケーションをロードすると、一部のセルのみがレンダリングされます。行をスクロールするか、行を選択すると、レンダリングが変わります。

問題が何であるかを説明するために、github でサンプル プロジェクトを作成しました。

スクリーンショット

セル レンダリングの実際のソース コードは、次の場所にあります

// CustomCell.m
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {

  if (![m_view superview]) {
    [controlView addSubview:m_view];
  }

  // The array controller only gets wrapped data items pack by the NSObjectTransformer.
  // Therefore, objectValue returns a NSObjectWrapper.
  // Unpack the wrapper to retreive the data item.
  DataItem* dataItem = [(NSObjectWrapper*)[self objectValue] original];
  [[m_view name] setStringValue:dataItem.name];
  [[m_view occupation] setStringValue:dataItem.occupation];
  [m_view setFrame:cellFrame];
}

controlViewが再描画しないようです。どうにか強制できませんか?

4

2 に答える 2

3

これはほぼ間違いなく、これを行うためのベスト プラクティスの方法ではありません。その理由については後で説明します。ただし、機能しているように見えます。cell クラスのdrawInteriorWithFrame:inView:メソッドを次のように置き換えます。

- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
    DataItem* dataItem = [(NSObjectWrapper*)[self objectValue] original];
    [[m_view name] setStringValue:dataItem.name];
    [[m_view occupation] setStringValue:dataItem.occupation];
    [m_view setFrame:cellFrame];

    NSData *d = [m_view dataWithPDFInsideRect:[m_view bounds]];
    NSImage *i = [[NSImage alloc] initWithData:d];
    [i setFlipped:YES];

    [i drawInRect:cellFrame fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
}

問題は、テーブル全体に対して 1 つの NSCell しか作成されないことです。これがセルの動作方法です。テーブル ビューはセルを作成し、setObject を呼び出し、続いて drawInterior を繰り返し呼び出して、セルにテーブル全体を描画させます。これは効率の観点からは素晴らしいことですが (NSCell クラスは 25MHz が高速なコンピューターだった頃に設計されたため、オブジェクト割り当ての数を最小限に抑えることを目的としていました)、ここで問題が発生します。

コードでは、ビューに値を入力し、そのフレームを設定して、必要に応じてテーブル ビューのサブビューとして追加します。ただし、NSCell のインスタンスは 1 つしかないため、表示できるビューは 1 つだけです。表示されていた 1 つのビューをテーブルの行の下に移動しただけです。

これを適切に行うには、NSTableView のサブビューとして追加したすべてのビューを追跡するためのデータ構造が必要です。また、セルが drawInterior… メソッドでビューを更新しているときに、正しいビューを調べて、どれが正しいかを調べる必要があります。それを更新します。また、これらすべてのビューをコードで割り当てる必要があります (または、少なくとも複数のコピーをロードできる別の nib にビューを移動します)。痛み。

私が書いたコードは本当に効率が悪いので、お粗末です。私が行ったことは、ビューを描画する必要があるたびに、ビューを画面外の画像バッファーに描画し、そのバッファーをテーブル ビューの正しい場所に描画することでした。そうすることで、ビューが 1 つしかないという問題を回避できました。これは、コードが必要なときにそのコンテンツの新しいコピーを取得して描画するためです。 ここに画像の説明を入力

于 2011-05-10T13:39:27.783 に答える
0

編集:説明については、他の回答を参照してください

実装しましたcopyWithZone:か?そのメソッドでビューをコピーまたは再作成する必要があります。そうしないと、異なるセルがビューを共有することになります (NSTableView がそのセルをコピーするため)。

于 2011-05-10T09:02:41.773 に答える