在.h文件中添加两个成员变量:
_target 和 _action
并且为这两个成员声明一个设置初值的方法:
- (void)addMyTarget:(id)target action:(SEL)action;
在.m文件中,当进去touchbegan时,让_target去执行以下动作:
[_target performSelector:_action withObject:self];
但是这个时候, _target是什么?_action是什么?
代理和targetAction的异同:
相同:首先他们都是让controller来做一些事情.我们要明白一点:我们举的例子是触摸事件发生的.但实际上这是view想要做什么事情的时候, 将逻辑部分交给controller来做的一种手段. 就算不是触摸事件,一样可以让代理或者addtargetaction来做这些事情哦.
不同:实现方法不一样,说不清楚,看例子吧:
targetAction: 代理:
1.创建RootViewController和RootView 代理相对来说就比较简单了, 你只需要明白代理是怎么回事就行了
2.现在我有一个视图view的一些行为需要让RootViewController来做,为了模拟这个主体,我再创建一个TouchView的视图.处理这视图的所有行为都放到RootViewController来做. 简单的说,你会描述,你就会写.
3.在TouchView.h中做如下的事情:
3.1)添加两个成员变量:
id _target; //目标. 让谁来做这些事儿.
SEL _action; //实现. 谁去实现这个方法.
3.2)为这两个成员变量添加设置方法:
- (void)addMyTarget:(id)target action:(SEL)action;"
谁是委托人?谁是代理?委托人需要什么功能?代理需要能提供什么功能?
4.在TouchView.m中的Touch..began事件处理方法中,添加这样一行代码:
[_target performSelector:_action withObject:self];
解释一下:通俗的讲:就是让_target去做_action这个动作.
深层次一点的说法是,_target是一个对象的主体,_target赋值后的对象一定有执行方法的能力.那么,首先,赋的值必须是一个对象.谁给_target赋值,谁就负责传一个对象过来.但是你代码写在这里,谁能给你赋值?谁知道你在谁?怎么给你值?
perform是一个登记的机制, 我猜啊, 有一张方法字典表, 记录了selector可以查找到的所有方法.当然我这么说一点根据都没有,我在瞎猜.先往下写一点,没准就明白了." 委托者是:TouchView 代理是RootViewController.
5.如果我们点击了屏幕发生了事件(点在了TouchView中),那么会发生什么事情?
根据响应者链规则1,我们找到了TouchView,发现TouchView中有处理方法(touch began).于是它就执行了[_target performSelector:_action withObject:self];这段代码….我靠,有controller毛事儿啊!
妈蛋,这performSelector肯定做了什么事情!" 委托人负责制定协议, 代理需要引入委托人的头文件(引入类和协议)
这里简直就是一个深坑. 委托人需要自己调方法, 但是这个方法是代理提供的.
SEL:是一种数据类型,它对方法进行了包装(说的好听),上面的_action的类型是SEL,也就是:@selector(fun)类型. 真正执行方法的时候,实在委托人的方法中,(在委托人的方法中),给代理发送了一个代理的方法, 转而代理去执行了那个方法.
SEL是一个结构体,它是对方法封装后得到的,所以,里面不单单应该有函数指针. 所以,这两种模式,都使用到了一ID类型.通用类型指针.
我明白了!关键是:包装的SEL类型数据它对应相应的方法地址,找到方法地址就可以调用方法 targetaction的id是作为一个替换的变量存在的.而委托人中的id<协议>类型指针,则是实实在在的指向了一个对象
"从整个ios的app流程来说,先走完RootViewController的Viewdidload方法, 那之前已经实例化了一个TouchView的对象.里面已经对这两个_target和_action赋值了.另外,TouchView已经是一个对象了,它当然能调用方法.所以,当发生点击事件的时候,_tar和_action都已经可以直接调用了.
在touchbegan方法中,[_target performSelector:_action withObject:self];变成了:
[RootViewController performSelector:@selector(touchViewAction:) withObject:TouchView];
这段代码在哪儿执行的呢?实在TouchView.m中的touchbegan中." id是所有对象类型的父指针,父类指针指向子类对象,这其实是一种多态现象.
"整个过程有点如下的意思:
我是TouchView类,我一会儿要接受触摸事件,做出一个动作, 我做动作的格式是
[_target performSelector:_action withObject:self];
你们一会儿谁初始化我,实例化我的对象的时候, 一定要把_target和_action给我赋上值啊.到时候我根据你们的赋值,去你们的对象里找方法." "于是乎:委托人需要提供:
1)协议(用到了class),
2)委托人需要提供一个id类型的通用指针,用来指向代理(具体的对象)可以通过指向不同的代理,用相同的调用代码执行处不同的结果(这tm的就是多态啊).
3)调用代码([self.delegate 方法],方法名相同但是因为delegate指向不同的对象,而每个对象都遵循实现这个方法的协议,所以他们能得到不同的结果, 在这里,只是一种结果, 是对代理协议模式的一种应用,一种阉割的应用方法."
相反, 代理 虱子多了不痒, 我只需要显示的将子视图的代理指针(id类型)指向自己,然后给你提供一个方法,就不管你了, 你什么时候需要执行我的代码,随便来. 反正我也不会被你中断.放马过来..
在TouchView.h中
@interface TouchView : UIView
{
// 这两个东西可以帮我们拆离代码
// 第一步:
id _target; //目标. 让谁来做这些事儿.
SEL _action; //实现. 谁去实现这个方法.
}
// 提供一个借口,添加目标和行动.
// 第二步:
- (void)addMyTarget:(id)target action:(SEL)action;
@end
在TouchView.m中
@implementation TouchView
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// 第三步:
[_target performSelector:_action withObject:self];
}
- (void)addMyTarget:(id)target action:(SEL)action
{
_target = target;
_action = action;
}
@end
在RootViewController中:先实例化对象 ,再报备(为_target和_action赋值, 最后是action方法.
-(void)loadView
{
self.rv = [[[RootView alloc] initWithFrame:[UIScreen mainScreen].bounds]autorelease];
self.view = _rv;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 报备.
[self.rv.tv addMyTarget:self action:@selector(touchViewAction:)];
//self.rv.backgroundColor = [UIColor greenColor];
}
- (void)touchViewAction:(TouchView *)sender
{
NSLog(@"%@",sender); // 如果performselector不传第二个参数withobject,那么这里的sender就不能用.
sender.backgroundColor =[UIColor colorWithRed:arc4random()%256/255.0 \
green:arc4random()%256/255.0 \
blue:arc4random()%256/255.0 \
alpha:1];
网友评论