iOS-模拟响应者链,自己hittest方法

来源:互联网 发布:mac上好玩的单机游戏 编辑:程序博客网 时间:2024/06/16 22:04

iOS-模拟响应者链,自己hittest方法

当用户触发的一个事件发生,UIKit会创建一个包含要处理的事件信息的事件对象。然后她会将事件对象放入active app’s(应用程序对象,每个程序对应唯一一个)事件队列。对于触摸事件,事件对象就是UIevent对象封装的一系列触摸集合。对于动作事件,这个事件对象依赖于使用的framework和你关心哪种动作事件。

事件通过特殊的路径传递直到被传递到一个可以处理该事件的对象。首先,单例的UIApplication对象从顶层的队列中获取事件,然后分发。典型的,它将事件发送到App的关键window(key window)对象,window则为了处理该事件而发送它到初始化对象(initial object),这个初始化对像依靠事件类型。

触摸事件(Touch events)。对于触摸事件,window对象首先会尝试将事件传递给事件发生的view。这个view就是所谓的hit-test view。寻找hit-test view的方法叫 hit-testing,具体描述可见“Hit-Testing Returns the View Where a Touch Occurred.”。

动作事件和远程控制事件(Motion and remote control events)。在这些事件中,window对象发送事件到第一个响应器。第一个响应器的描述见“The Responder Chain Is Made Up of Responder Objects.”。事件传递路径的最终目的时找出能处理和响应该事件的对象。因此,UIKit给适合处理该事件的对象发送事件。对于触摸事件,这个对象就是hit-test view,对于其他事件,这个对象就是第一个响应器(first responder)。

下面模拟实现hittest方法。

// hitTest:方法内部的参考实现- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{    NSLog(@"%@----hitTest:", [self class]);    // 如果控件不允许与用户交互那么返回 nil    if (self.userInteractionEnabled == NO || self.alpha <= 0.01 || self.hidden == YES) {        return nil;    }    // 如果这个点不在当前控件中那么返回 nil    if (![self pointInside:point withEvent:event]) {        return nil;    }    // 从后向前遍历每一个子控件    for (int i = (int)self.subviews.count - 1; i >= 0; i--) {        // 获取一个子控件        UIView* lastVw = self.subviews[i];        // 把当前触摸点坐标转换为相对于子控件的触摸点坐标        CGPoint subPoint = [self convertPoint:point toView:lastVw];        // 判断是否在子控件中找到了更合适的子控件        UIView* nextVw = [lastVw hitTest:subPoint withEvent:event];        // 如果找到了返回        if (nextVw) {            return nextVw;        }    }    // 如果以上都没有执行 return, 那么返回自己(表示子控件中没有"更合适"的了)    return self;}
0 0
原创粉丝点击