代理
- 思路:如果某个控件需要做某件事,自己没法做,就让代理去做,
通知代理去做某件事
,而代理要做这件事需要两个参数:谁让它做,和做这件事的一个参数(这个参数也可以没有)。如果代理实现了代理方法,那么这个控件就把这两个参数传给代理。最后代理根据这两个参数在实现的代理方法里把事情完成。
案例一:传数据给代理(类似tableView的监听类型的代理方法)
- 传递控制器里面:如果代理实现了_editDelegate respondsToSelector:@selector(editVc:didSaveUser:)方法,那么就调用[_editDelegate editVc:self didSaveUser:_nUser]方法把(XMGEditViewController)self和(XMGUser *)newUser这两个参数传过去
if ([_editDelegate respondsToSelector:@selector(editVc:didSaveUser:)]) {
[_editDelegate editVc:self didSaveUser:_nUser];
}
- 传递控制器头文件里:申明代理方法,代理属性
@protocol XMGEditViewControllerDelegate <NSObject>
@optional
- (void)editVc:(XMGEditViewController *)editVc didSaveUser:(XMGUser *)newUser;
@end
@property (weak,nonatomic) id <XMGEditViewControllerDelegate> editDelegate;
- 接受控制器里:遵守协议,成为代理editVc.editDelegate = self;,并且实现方法,接受数据得到传值
- (void)editVc:(XMGEditViewController *)editVc didSaveUser:(XMGUser *)newUser{
self.allDetailVc.nUser = newUser;
}
案例二:代理成为数据源(类似tableView里的数据源代理)
- 自定义View头文件里:
@protocol XMGWaterFlowLayoutDelagte<NSObject>
@optional
-(CGFloat)waterFlowLayout:(XMGWaterFlowLayout *)layout cellHeightWithCellWidth:(CGFloat)cellWidth atIndexPath:(NSIndexPath *)indexPath;
@end
@property (nonatomic, weak) id<XMGWaterFlowLayoutDelagte> delegate;
- 自定义的View.m里:
// 如果代理实现了代理方法,那么h就等于这个方法的返回值
if ([self.delegate respondsToSelector:@selector(waterFlowLayout:cellHeightWithCellWidth:atIndexPath:)]) {
h = [self.delegate waterFlowLayout:self cellHeightWithCellWidth:w atIndexPath:indexPath];
- 外界控制器里:实现代理方法,传输数据
-(CGFloat)waterFlowLayout:(XMGWaterFlowLayout *)layout cellHeightWithCellWidth:(CGFloat)cellWidth atIndexPath:(NSIndexPath *)indexPath{
return 100;
}
拿别的对象作为代理
- 注意:代理是弱引用,所以要拿别的对象作为代理,下面这么做是错的
所以一般用控制器作为代理,因为控制器不会死
scrollView.delegate = [[XMGCat alloc] init];//这个猫刚创建就死了
- 必须再拿一个强指针指着它
@property (nonatomic, strong) XMGCat *cat;
self.cat = [[XMGCat alloc] init];
scrollView.delegate = self.cat;
- 为什么代理用弱指针?
- 因为一般用控制器作为代理,如果用强指针,那么控制器经过循环会强引用代理,代理再强引用控制器,循环强引用,那么他们永远不会死了
代理的名称规律
- 协议名称一般是控件类名+delegate,比如UIScrollViewDelegate
- 代理方法一般是控件名开头,比如UIScrollView的代理方法一般以UIScrollView开头
代理与通知的选择
共同点 :利用通知和代理都能完成对象之间的通信(比如A对象告诉D对象发生了什么事情, A对象传递数据给D对象)
不同点 :
- 代理 : 1个对象只能告诉另1个对象发生了什么事情
- 通知 : 1个对象能告诉N个对象发生了什么事情, 1个对象能得知N个对象发生了什么事情