查看各种UICollectionView...
头文件,并观看WWDC 2012 Session 219 - Advanced Collection Views and Building Custom Layouts视频(从大约 6:50 开始),似乎可扩展委托模式利用了动态类型来确保布局可以正确访问它的扩展委托方法。
简而言之...
- 如果您使用自己的委托定义自定义布局,请在布局的头文件中定义该委托协议。
- 您的委托对象(通常
UI(Collection)ViewController
是管理集合视图的委托对象)应声明自己以支持此自定义协议。
- 如果您的布局只是其
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
流布局是否使用了私有子类/类别来防止需要进行类型转换。为了进一步强调这一点,Apple 不鼓励UICollectionView
在文档中进行子类化(iOS 的集合视图编程指南:创建自定义布局):
避免继承 UICollectionView。集合视图很少或没有自己的外观。相反,它会从您的数据源对象中提取其所有视图,并从布局对象中提取所有与布局相关的信息。
所以我们开始了。并不复杂,但值得知道如何以范式友好的方式进行操作。