iOS之targetAction代理模式

2017-06-13  本文已影响0人  wps_pro

在.h文件中添加两个成员变量:
_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];
上一篇 下一篇

猜你喜欢

热点阅读