美文网首页
iOS开发-消息传递方式-target-action

iOS开发-消息传递方式-target-action

作者: 张囧瑞 | 来源:发表于2018-02-28 16:35 被阅读240次

    target-action是iOS中UIControl控件下使用的最常见的消息传递方式,target-action在中文中就是目标-动作,也算是一种简单的设计模式.

    主要的功能就是在发生某种事情的时候,给某某对象发送一个消息。一般情况下是在我们点击按钮,或者是滑动进度条之类的情况下发送给目标一个消息。比如说,当我们肚子饿了的时候就告诉大脑要去找东西吃。

    target_action.jpg

    方法调用

    target-action的方法调用非常简单,一般实现一个函数:

    - (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;
    

    target

    target就是目标,如果用之前的例子来比喻的话就是我们的大脑。

    action

    action就是动作,用之前的例子来比喻的话就是去找东西吃这个动作。

    events

    events是事件,比如说肚子饿了,或者口渴了,是出发动作的条件。

    使用

    这里用给UIButton添加点击事件来做一个🌰。

        [targetBtn addTarget:self action:@selector(targetBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    

    这样就可以给targetBtn添加一个按下的事件,当用户按下按钮时,按钮就会告诉self,调用targetBtnClicked:方法。

    UIControlEvents

    UIControlEvents主要是事件的触发条件。

    typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
        UIControlEventTouchDown                                         = 1 <<  0,      // on all touch downs
        UIControlEventTouchDownRepeat                                   = 1 <<  1,      // on multiple touchdowns (tap count > 1)
        UIControlEventTouchDragInside                                   = 1 <<  2,
        UIControlEventTouchDragOutside                                  = 1 <<  3,
        UIControlEventTouchDragEnter                                    = 1 <<  4,
        UIControlEventTouchDragExit                                     = 1 <<  5,
        UIControlEventTouchUpInside                                     = 1 <<  6,
        UIControlEventTouchUpOutside                                    = 1 <<  7,
        UIControlEventTouchCancel                                       = 1 <<  8,
    
        UIControlEventValueChanged                                      = 1 << 12,     // sliders, etc.
        UIControlEventPrimaryActionTriggered NS_ENUM_AVAILABLE_IOS(9_0) = 1 << 13,     // semantic action: for buttons, etc.
    
        UIControlEventEditingDidBegin                                   = 1 << 16,     // UITextField
        UIControlEventEditingChanged                                    = 1 << 17,
        UIControlEventEditingDidEnd                                     = 1 << 18,
        UIControlEventEditingDidEndOnExit                               = 1 << 19,     // 'return key' ending editing
    
        UIControlEventAllTouchEvents                                    = 0x00000FFF,  // for touch events
        UIControlEventAllEditingEvents                                  = 0x000F0000,  // for UITextField
        UIControlEventApplicationReserved                               = 0x0F000000,  // range available for application use
        UIControlEventSystemReserved                                    = 0xF0000000,  // range reserved for internal framework use
        UIControlEventAllEvents                                         = 0xFFFFFFFF
    };
    
    

    target-action 传值

    tag

    target-action 模式传值一般通过tag来实现。

    tag是一个无符号整形,所有的UIKit控件都有这个属性,在设定控件时可以加上tag值,在响应事件action中可以获取到sender,通过获取sender的tag来达到传值的功能。

    添加tag:

        UIButton *targetBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        targetBtn.frame = CGRectMake(0, HEIGHT/2-50, WIDTH, 100);
        targetBtn.tag = 100;
        [targetBtn setTitle:@"点我" forState:UIControlStateNormal];
        [targetBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [targetBtn addTarget:self action:@selector(targetBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
    

    在action中获取tag值:

    - (void)targetBtnClicked:(UIButton *)sender
    {
        NSLog(@"我被点击了");
     
        NSLog(@"tag:%ld",(long)sender.tag);    
    }
    
    

    category 添加传值方法

    tag只能传递一个整形数字,这有很大的局限性,平时我们开发时可能还需要传递一些复杂的数据,这个时候tag就显得很局促了。

    所以我们可以通过给父类添加category的方式,添加一个info的字典,用来传递消息。

    添加category:

    #import <Foundation/Foundation.h>
    
    @interface NSObject (MPTargetActionPassing)
    
    @property (nonatomic ,retain) NSDictionary          *info;
    
    @end
    
    

    使用runtime实现info的getter方法和setter方法:

    #import "NSObject+MPTargetActionPassing.h"
    #import <objc/runtime.h>
    
    @implementation NSObject (MPTargetActionPassing)
    
    - (void)setInfo:(NSDictionary *)info
    {
        objc_setAssociatedObject(self, @"info", info, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (NSDictionary *)info
    {
        return objc_getAssociatedObject(self, @"info");
    }
    
    
    @end
    
    

    在使用时设置info的值:

        UIButton *targetBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        targetBtn.frame = CGRectMake(0, HEIGHT/2-50, WIDTH, 100);
        targetBtn.tag = 100;
        [targetBtn setTitle:@"点我" forState:UIControlStateNormal];
        [targetBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [targetBtn addTarget:self action:@selector(targetBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
        [targetBtn setInfo:@{@"id":@"12138",@"name":@"target-action"}];
        
        [self.view addSubview:targetBtn];
    
    

    在action中获取info中的值:

    - (void)targetBtnClicked:(UIButton *)sender
    {
        NSLog(@"我被点击了");
     
        NSLog(@"tag:%ld",(long)sender.tag);
        
        NSDictionary *info = sender.info;
        
        NSLog(@"%@",info);
        
    }
    
    

    这里我们是对NSObject进行的一个拓展,写完这个拓展之后,只要在继承了NSObject的类的控件使用时,引入头文件:

    #import "NSObject+MPTargetActionPassing.h"
    

    就可以随意的传递值了。

    Demo

    最后放个Demo](https://github.com/rshinich/MessagePassing)。

    这里只是iOS中消息传递方式的第一部分,这种传值的方式使用到了runtime,意味着所有的NSObject子类都可以使用这个info,所以平时还是不是很建议用这种方式,如果平时想要传递一些复杂的数据可以通过其他的方式来做,比如代理、block等。

    本文章仅限个人学习,如果有什么地方写的不对的还希望各位大佬批评指正。

    相关文章

      网友评论

          本文标题:iOS开发-消息传递方式-target-action

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