zoukankan      html  css  js  c++  java
  • iOS 事件响应者链的学习(也有叫 UI连锁链)

    当发生事件响应的时候,必须知道由谁来响应事件.在iOS中,由响应链来对事件进行响应,所有的事件响应的类都是继承于UIResponder的子类,响应链是一个由不同对象组成的层次结构,其中每个对象将依次获得响应事件消息的机会

    发生触摸事件后,系统将事件加入到由UIApplication管理的事件 队列 

    好处:遵循第一响应原则,总会优先处理队列中排在最前面的事件.(栈是先进后出 不符合业务逻辑)

    (1)事件传递(链)

    1.传递链中时没有controller的,因为controller本身不具有大小的概念

    2.用户的触摸事件首先会由系统截获,进行包装处理等。然后递归遍历所有的view,进行碰触测试(hitTest),直到找到可以处理事件的view

    大致的过程application –> window –> root view –>……–>lowest view 

    网上一个很直观的解释图

     

    (2)响应链

    1.响应链中是有controller的,因为controller继承自UIResponder

    2.当有view能够处理触摸事件后,开始响应事件。

            系统会调用view的以下方法:

            - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

            - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

            - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

            - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

            可以多对象共同响应事件。只需要在以上方法重载中调用super的方法。

            大致的过程initial view –> super view –> …..–> view controller –> window –> Application

    我记得 前年被一位CTO面试的时候 问到过这个问题 ,原话大概是说”触发一个按钮,怎么截获 它的触发消息”;当时说得一塌糊涂 ,但是由于 有个创意性的问题分析回答得特别到位 ,还夸奖了我,说我有想法,他还感冒了,说要去擤鼻子 然后就没在回来 .比较遗憾的面试,其实不要估计我是女生呀,我不怕拒绝,也没说原因呢,就没有然后了.

    现在想起来,估计这个”事件传递响应者链”的原理真的很重要,如今学习的更加深入,自然而然就会去讨论学习,在开发中运用起来. 真是成长如蜕啊.

    举例:

    其实开发中,真的好多地方可以运用到这个方法,用来截获一些信息啦,处理消息,获取对象,修改响应,或者具体知道自己实现一个方法到底该是怎样一个流程等.

    需求:在cell上添加一个按钮,点击一下进入下一个导航页面.

    之前通常的做法是,”  [cell.btn addTarget:  blabla ]” 写在视图控制器里面 ,因为这样很好的调用到viewController.

    现在知道了事件响应者链的原理  就利用这个机制解决一下吧

    2.1首先创建一个UIView 类别 扩展 一个实例方法 根据"事件响应者链原理" :判读UIView上的点击事件,如果已经传递到了UIViewController,则就进行处理。获取这个视图控制器.

    //
    //  UIView+EventLink.h
    //  TableViewDemo
    //
    //  Created by HF on 16/2/26.
    //  Copyright © 2016年 HF-zhjh. All rights reserved.
    //
    #import <UIKit/UIKit.h>
    @interface UIView (EventLink)
    -(UIViewController *)viewController;
    @end
    
    //
    //  UIView+EventLink.m
    //  TableViewDemo
    //
    //  Created by HF on 16/2/26.
    //  Copyright © 2016年 HF-zhjh. All rights reserved.
    //
    
    #import "UIView+EventLink.h"
    @implementation UIView (EventLink)
    //为UIView扩展一个方法,用于响应事件链
    -(UIViewController *)viewController{
        UIResponder *nexRes=[self nextResponder];                                                      
        do {
            //判读当前的响应者是否UIViewController
            if ([nexRes isKindOfClass:[UIViewController class]]) {
                //是否直接处理
                return  (UIViewController*)nexRes;
            }else{
                //否则继续寻找
                nexRes=[nexRes nextResponder];                                                  
            }
        } while (nexRes!=nil);
        return nil;
    }
    @end

    通过为UIView扩展一个分类(类别)方法之后,我们就可以在Cell中调用分类方法(viewController)处理事件响应了。

    //按钮事件
    //UITableViewCell 继承于UIView 所以 现在 cell 多了一个属性 就是 viewController 可以直接用了
    //其实还算是很方便 可读性也很高
    -(void)buttonAction:(UIButton *)btn{ //使用事件响应者 UIViewController *view=[[UIViewController alloc] init]; [self.viewController.navigationController pushViewController:view animated:YES]; [view release]; }

     (3)几种无法接受触摸事件的情况

    1.不接收用户交互

    userInteractionEnabled = NO

    2.隐藏
    hidden = YES

    3.透明
    alpha = 0.0 ~ 0.01

    提示:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的

  • 相关阅读:
    FORM中的get post方法区别
    二叉树优势
    Map 排序
    ajax+MultipartFile上传文件到本地
    阿里巴巴开发手册
    poi快速导入导出excel表格
    String.trim()、.contains()等的作用
    eclipse导入ssm框架的项目,报tomcat无法启动的错误,如下:
    lesson5_oa文件操作
    lesson4_函数
  • 原文地址:https://www.cnblogs.com/someonelikeyou/p/5220778.html
Copyright © 2011-2022 走看看