セルから CollectionView への後方参照を iVar またはプロパティとして追加しないでください。これは、本当に (本当に) 不適切な相互参照 (objA が objB を指し、objB が objA を指す) になるためです。コンパイル エラー (@class
ステートメントでひどく修正される可能性があります) などの小さな問題に加えて、これにより、割り当て解除できないオブジェクト、メモリ リーク、ゾンビなどの重大な問題が発生します。
経験則は次のとおりです。
親は子供のことを知っていますが、子供は親のことを知ってはいけません。
言い換えれば、CollectionView はそのセルを認識していますが、セルは CollectionView を認識するべきではありません。
可能な解決策
タスクとソリューションを再設計します。セルではなく、collectionView にタップ ジェスチャ レコグナイザーを追加することもできます。選択したセルを提供する -indexPathForItemAtPoint: があります。
逆参照が絶対に必要な場合:プロトコルを定義し、デリゲートを使用します。Cocoa / Cocoa Touchでよくあるデザインパターンです。デリゲートの設計パターンについて読む必要がありますが、要するに、これがその方法です。
セルでプロトコルを定義します (このプロトコルを定義することにより、セルは親のタイプを認識していないことを思い出してください。「親」で使用可能なメソッドが 1 つ以上あることを認識しているだけです)。
// in cell.h
@protocol MyCellProtocol
- (IBAction)doSomething:(id)sender;
@end
タイプidのデリゲートを追加します(これは、プロトコルに準拠している限り、任意のオブジェクトにすることができることを意味します。つまり、これはあなたのcollectionViewになりますが、それへの参照を持つ必要はありません!
// in cell.h
@property (assign) id<MyCellProtocol> cellDelegate;
これで、セルでデリゲートを呼び出すことができます:
// in cell.m, some method:
[self.cellDelegate doSomething:nil];
最後に、デリゲートを設定する必要があります。UICollectionViewController でセルを作成/セットアップするときは、コントローラーをデリゲートとして設定します。
// in collectionViewController.m
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell =
[self.collectionView dequeueReusableCellWithReuseIdentifier:@"myCell"
forIndexPath:indexPath];
cell.cellDelegate = (id<MyCellProtocol>)self;