美文网首页
iOS之targetAction代理模式

iOS之targetAction代理模式

作者: wps_pro | 来源:发表于2017-06-13 15:49 被阅读0次

    在.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];
    

    相关文章

      网友评论

          本文标题:iOS之targetAction代理模式

          本文链接:https://www.haomeiwen.com/subject/rkqdqxtx.html