8

デコレータパターンを使用してUICollectionViewCellsを「装飾」しようとしています。

たとえば、私が持っている場合

 BaseCell : UICollectionViewCell 

私はこのようなことをしたいと思っています:

 BaseCell *cell = [[BaseCell alloc] initWithFrame]
 cell = [[GlowingCell alloc] initWithCell:cell];
 cell = [[BorderedCell alloc] initWithCell:cell];
 cell = [[LabelledCell alloc] initWithCell:cell];

 // cell is now a glowing, bordered, labelled cell.

デコレータパターンはこの種のものにはかなりきれいだと思いますが、コレクションビューに適用するのは難しいです。

まず、UICollectionViewControllersで、次のようにクラスを登録する必要があります。

 [self.collectionView registerClass:cellClass forCellWithReuseIdentifier:cellIdentifier];

そのため、自分のインスタンスを作成する機会がありません。

次に、デコレータが「純粋でない」オブジェクト、つまり、ゼロから作成したのではなく、独自のプロパティと動作(UICollectionViewCellなど)を持つオブジェクトを装飾するのにどのように役立つかがわかりません。上記の例では、cellはLabelledCellの新しいインスタンスを表しているため、UICollectionViewがメソッドを呼び出す場合、たとえば、Decorator基本クラスで特にこれを行わない限りisSelected、これは呼び出されます。aLabelledCellInstance.isSelected

 - (BOOL)isSelected {
      return self.decoratedCell.isSelected;
 }

これは1つのメソッドには問題ありませんが、のすべてのメソッドをオーバーライドする必要があるとは限りませんUICollectionViewCell。使用する必要がありforwardInvocation:ますか?

私はこのパターンを悪用していますか?代替手段はありますか?なぜなら、次のような基本的なメソッドをオーバーライドする必要がある場合に、本で非常にうまく機能するからです。

 getPrice() {
      return decoratedObject.getPrice() + 1.10f;
 }

..しかし、既存のUI要素をカスタム動作で実際に装飾するという目的に合わせるのは難しいようです。

ありがとう

編集:私が避けようとしているのは、次のようなクラスを持つことです:

  • GlowingBorderedCell
  • LabelledGlowingBorderedCell

紙の上では、デコレータは私が達成しようとしていることの完璧な候補ですが、実装は絶対に私を困惑させています。

4

2 に答える 2

4

まず、DecoratorパターンではBaseDecorator、装飾されたオブジェクトに呼び出しを転送できるように、のすべての基本メソッドをオーバーライドする必要があります。そして、これを行うには、すべてのメソッドをオーバーライドするか、できれば、を使用しますforwardInvocation:。また、他のすべてのデコレータはのサブクラスになるためBaseDecorator、変更するメソッドをオーバーライドするだけで済みます。

次に、このCollectionView問題については、通常のsでデコレータパターンを使用してから、セルUIViewの装飾ビューを使用することをお勧めします。contentView例を見てみましょう:

すべてBaseCellViewのデコレータのスーパークラスとなるクラスがあります。

BaseCellView : UIView;
GlowingCellView: BaseCellView;
BorderedCell: BaseCellView;
LabelledCell: BaseCellView;

そして、私たちはまだBaseCellサブクラスである私たちのクラスを持っていますUICollectionViewCell

BaseCell : UICollectionViewCell;

これで、UICollectionViewControllers常にのインスタンスを作成し、BaseCellそれを構成する機会が与えられます。ここで、次のことを行います。

BaseCellView *cellView = [[BaseCellView alloc] initWithFrame]
cellView = [[GlowingCellView alloc] initWithCellView:cellView];
cellView = [[BorderedCellView alloc] initWithCellView:cellView];
cellView = [[LabelledCellView alloc] initWithCellView:cellView];
cell.contentView = cellView;

UICollectionViewCellまた、必要に応じて、デコレータに転送することもできます。

于 2013-02-01T19:21:48.363 に答える
3

これが私がこのテクニックを説明した投稿ですセルではなく、を装飾することを選択しましたがUITableView、コレクションビューに簡単に適合させることができます。かなり長い間読んでいるので、ここでは簡単な要約のみを作成します。

  • デコレータは、すべてのメッセージをデコレートされたオブジェクトに転送できるようにするためのプロキシオブジェクトである必要があります
  • それを実現するためにデコレータでオーバーライドする必要のあるメソッドは複数ありますが、その中にrespondsToSelectorforwardingTargetForSelector
  • 完了すると、かなりきれいなデコレータをチェーンできるようになります。

例えば:

dec = [[DEFooterDecorator alloc] initWithDecoratedObject:dec];
dec = [[DEHeaderDecorator alloc] initWithDecoratedObject:dec];
dec = [[DEGreenCellDecorator alloc] initWithDecoratedObject:dec];
于 2013-02-01T19:34:05.367 に答える