响应链之nextResponder

作者: 此心不改 | 来源:发表于2016-07-06 01:57 被阅读2515次

    在cocochina上看到一篇文章《巧用UIResponder进行事件传递》,发现了UIResonder类的nextResponder属性。由于原文涉及的内容比较多,所以我自己专门将该知识点进行了一下整理。这是一个很有用的属性,对于UIView,nextResponder就是其SuperView或者ViewController,这样在做事件传递的时候可以不用设置delegate或block。

    看一个例子前,我先提一下2个知识点:
    • 事件响应链:当用户点击一个UIView时,系统会产生一个事件,并将其放入UIApplication的事件队列中。然后该事件会顺着这条链传递到用户点击的那个UIView:UIApplication->UIWindow->RootView->...->Subview。然后开始处理这个事件,若Subview不处理,事件将会传递给其�视图控制器,若没有控制器则传给其superView,最后传给UIWindow,UIApplication。若UIApplication还是没处理则将事件传给nil。
    图片来源:伯乐在线-alanwangmodify.png
    • UIResponder具有nextResponder属性,也就是其SuperView或是UIViewConterller等。UIView是UIResponder的子类,所以UIView及其子类都能使用此属性。

    好了,现在可以看这个应用实例:点击cell上的按钮,将事件传给ViewController,显示点击的cell的index。之前没用nextResponder属性,把事件从cell上的按钮传到ViewController需要将VIewController作为参数传入cell或者设置代理与block。

    Paste_Image.png
    Paste_Image.png

    1.首先为UIResponder创建一个分类,

     #import<UIKit/UIKit.h>
    @interface UIResponder (Router)
    -(void)routerEvent:(id)info;
    @end 
    
     #import "UIResponder+Router.h"
    @implementation UIResponder (Router)
    -(void)routerEvent:(id)info{
        [self.nextResponder routerEvent:info];
    }
    @end ```
    
    2.然后在ViewController中加入一个UITableview和UILable;
    ```Object-C
    #import "ViewController.h"
    #import "TableViewCell.h"
    #import "UIResponder+Router.h"
    @interface ViewController ()<UITableViewDataSource>
    @property(strong, nonatomic)UILabel *mLbl;
    @property(strong, nonatomic)UITableView *mTableView;
    @end
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        CGFloat w0 = self.view.bounds.size.width;
        CGFloat h0 = 80.;
        _mLbl = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, w0, h0)];
        _mLbl.backgroundColor = [UIColor orangeColor];
        _mLbl.textColor = [UIColor whiteColor];
        _mLbl.font = [UIFont systemFontOfSize:35.];
        _mLbl.textAlignment = NSTextAlignmentCenter;
        CGFloat w1 = w0;
        CGFloat h1 = self.view.bounds.size.height - h0;
        CGFloat y1 = h0;
        _mTableView = [[UITableView alloc]initWithFrame:CGRectMake(0, y1, w1, h1)];
        _mTableView.dataSource = self;
        [_mTableView registerClass:[TableViewCell class] forCellReuseIdentifier:@"CELL"];
        
        [self.view addSubview:_mLbl];
        [self.view addSubview:_mTableView];
    }
    
    #pragma mark UITableViewDataSource
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return 20;
    }
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CELL" forIndexPath:indexPath];
        [cell reloadData:indexPath.row];
        
        return cell;
    }
    //接收事件
    -(void)routerEvent:(id)info{
        _mLbl.text = info;
    }
    
    @end
    

    TableViewCell;

    #import <UIKit/UIKit.h>
    
    @interface TableViewCell : UITableViewCell
    
    -(void)reloadData:(NSInteger)index;
    
    @end 
    
    #import "TableViewCell.h"
    #import "UIResponder+Router.h"
    
    @interface TableViewCell ()
    
    @property(assign, nonatomic)NSInteger mIndex;
    @property(strong, nonatomic)UIButton *mBtn;
    
    @end
    
    @implementation TableViewCell
    
    -(void)reloadData:(NSInteger)index{
        _mIndex = index;
        [_mBtn setTitle:[NSString stringWithFormat:@"%li",_mIndex] forState:UIControlStateNormal];
    }
    
    -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            _mBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, self.frame.size.width*0.5, self.frame.size.height*0.8)];
            _mBtn.backgroundColor = [UIColor purpleColor];
            [_mBtn addTarget:self action:@selector(btnAction) forControlEvents:UIControlEventTouchUpInside];
            [self addSubview:_mBtn];
        }
        return self;
    }
    
    //传递事件
    -(void)btnAction{
    
        [self routerEvent:[NSString stringWithFormat:@"%li",_mIndex]];
    }
    
    @end```
    
    总得来说,拿到nextResponder就拿到了view的下一个事件响应者,至于怎么操作,可以自己拓展。

    相关文章

      网友评论

      本文标题:响应链之nextResponder

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