さまざまなUICollectionView...
ヘッダー ファイルを確認し、WWDC 2012 セッション 219 - 高度なコレクション ビューとカスタム レイアウトの構築のビデオ (約 6:50 以降) を見ると、拡張可能なデリゲート パターンが動的型付けを利用して、レイアウトが適切にアクセスできるようになっているようです。その拡張デリゲート メソッド。
要するに...
- 独自のデリゲートを使用してカスタム レイアウトを定義する場合は、レイアウトのヘッダー ファイルでそのデリゲート プロトコルを定義します。
- デリゲート オブジェクト (通常は
UI(Collection)ViewController
コレクション ビューを管理する) は、このカスタム プロトコルをサポートするように自身を宣言する必要があります。
- レイアウトが単なる 1
UICollectionViewFlowLayout
つまたはそのサブクラスである場合、これは単に への適合を宣言することを意味しUICollectionViewDelegateFlowLayout
ます。
- デリゲートのインターフェイスにレイアウト ヘッダーを挿入し
.m
たくない場合は、ファイルのクラス拡張で自由にこれを行ってください。#import
- レイアウトからデリゲート メソッドにアクセスするには、コレクション ビューのデリゲートを呼び出します。
- レイアウトの
collectionView
プロパティを使用し、必要なプロトコルに準拠するオブジェクトにデリゲートをキャストして、コンパイラを納得させます。
respondsToSelector:
オプションのデリゲート メソッドを呼び出す前に、デリゲートが通常どおりであることを確認することを忘れないでください。実際、必要に応じて、すべてのメソッドに対してこれを実行しても害はありません。型キャストは、デリゲートが必要なメソッドを実装する実行時の保証がないことを意味するためです。
コードで...
そのため、一部の情報のデリゲートを必要とするカスタム レイアウトを実装する場合、ヘッダーは次のようになります。
@protocol CollectionViewDelegateCustomLayout <UICollectionViewDelegate>
- (BOOL)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
shouldDoSomethingMindblowingAtIndexPath:(NSIndexPath *)indexPath;
@end
@interface CustomLayout : UICollectionViewLayout
// ...
@end
あなたのデリゲートは適合性を宣言します (私はここの実装ファイルでそうしました):
#import "CustomLayout.h"
@interface MyCollectionViewController () <CollectionViewDelegateCustomLayout>
@end
@implementation
// ...
- (BOOL)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)layout
shouldDoSomethingMindblowingAtIndexPath:(NSIndexPath *)indexPath
{
return [self canDoSomethingMindblowing];
}
// ...
@end
レイアウトの実装では、次のようにメソッドにアクセスします。
BOOL blowMind;
if ([self.collectionView.delegate respondsToSelector:@selecor(collectionView:layout:shouldDoSomethingMindblowingAtIndexPath:)]) {
blowMind = [(id<CollectionViewDelegateCustomLayout>)self.collectionView.delegate collectionView:self.collectionView
layout:self
shouldDoSomethingMindblowingAtIndexPath:indexPath];
} else {
// Perhaps the layout also has a property for this, if the delegate
// doesn't support dynamic layout properties...?
// blowMind = self.blowMind;
}
とにかくデリゲートがそのメソッドに応答することを事前にチェックしているので、ここで型キャストしても安全であることに注意してください。
確たる証拠...
これは憶測にすぎませんが、Apple がUICollectionViewDelegateFlowLayout
プロトコルを管理する方法に問題があるのではないかと思います。
- フロー レイアウトにはプロパティがない
delegate
ため、呼び出しはコレクション ビューのデリゲートを経由する必要があります。
UICollectionViewController
拡張フロー レイアウト デリゲートに公に準拠していません (別のプライベート ヘッダーで準拠しているとは思えません)。
UICollectionView
のdelegate
プロパティは、「ベース」UICollectionViewDelegate
プロトコルへの準拠のみを宣言します。UICollectionView
繰り返しますが、型キャストの必要性を防ぐために、フロー レイアウトで使用されている のプライベート サブクラス/カテゴリがあるとは思えません。この点にさらに重みを加えるために、AppleUICollectionView
はドキュメントでサブクラス化をまったく推奨していません ( iOS 用コレクション ビュー プログラミング ガイド: カスタム レイアウトの作成)。
UICollectionView のサブクラス化は避けてください。コレクション ビューには、独自の外観がほとんどまたはまったくありません。代わりに、データ ソース オブジェクトからすべてのビューを取得し、レイアウト オブジェクトからすべてのレイアウト関連情報を取得します。
それでは、行きましょう。複雑ではありませんが、パラダイムに適した方法で行う方法を知っておく価値があります。