iOS——事件响应链

一、原理

1. UIResponder 类有一个名为 nextResponder 的属性,凡是 UIResponder 的对象或其子类对象都可以通过该属性组成一个 响应对象链

2. nextResponder 属性的指向
1)当某个 UIView 对象属于某个 UIViewController 对象时,则该 UIView 对象的 nextResponder 属性就指向该 UIViewController 对象;而该 UIViewController 对象的 nextResponder 属性指向该 UIView 对象的父视图
2)当某个 UIView 对象不属于任何 UIViewController 对象时,该 UIView 对象的 nextResponder 就指向其父视图
3)最顶层的父视图是 UIWindow 对象,而 UIWindow 对象指向 UIApplication 单例类

如图


3. 如果某个 UIResponder 对象没有处理传给它的事件,该对象就会将未处理的消息发送给自己的 nextResponder 对象;touchesBegin:withEvent: 此类消息就是这样实现的;如果直到最后的 UIApplication 对象也无法处理,系统就会抛弃该事件

二、实例


1. 详细代码

// LHSubView.h
#import <UIKit/UIKit.h>

@interface LHSubView : UIView

@end

// LHSubView.m
#import "LHSubView.h"

@implementation LHSubView

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    NSLog(@"subView 响应");
    
    // 手动向下传递
    [[self nextResponder]touchesBegan:touches withEvent:event];

}

@end

// LHMainView.h
#import <UIKit/UIKit.h>

@interface LHMainView : UIView

@end

// LHMainView.m
@implementation LHMainView

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    NSLog(@"mainView 响应");
    
    // 手动向下传递
    [[self nextResponder]touchesBegan:touches withEvent:event];

}

@end

// LHRootViewController.h
#import <UIKit/UIKit.h>

@interface LHRootViewController : UIViewController

@end

// LHRootViewController.m
#import "LHRootViewController.h"
#import "LHMainView.h"
#import "LHSubView.h"

@interface LHRootViewController ()

@property (nonatomic, strong) LHMainView * mainView;

@property (nonatomic, strong) LHSubView * subView;

@end

@implementation LHRootViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建主视图
    _mainView = [[LHMainView alloc] initWithFrame:CGRectMake(50, 50, 200, 300)];
    
    _mainView.backgroundColor = [UIColor orangeColor];
    
    // 创建子视图
    _subView = [[LHSubView alloc] initWithFrame:CGRectMake(30, 30, 100, 200)];
    
    _subView.backgroundColor = [UIColor purpleColor];
    
    [_mainView addSubview:_subView];
    
    [self.view addSubview:_mainView];
    
    self.view.backgroundColor = [UIColor blueColor];
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    NSLog(@"LHRootViewController 响应");
    
    // 手动向下传递
    [[self nextResponder]touchesBegan:touches withEvent:event];

}

@end

// LHMyWindow.h
#import <UIKit/UIKit.h>

@interface LHMyWindow : UIWindow

@end

// LHMyWindow.m
@implementation LHMyWindow

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {

    NSLog(@"MyWindow 响应");
    
    // 手动向下传递
    [[self nextResponder]touchesBegan:touches withEvent:event];

}

@end

// AppDelegate.h
#import "LHMyWindow.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) LHMyWindow *window;

@end

// AppDelegate.m
@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    self.window = [[LHMyWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    
    [self.window makeKeyAndVisible];
    
    self.window.rootViewController = [[LHRootViewController alloc] init];
    
    self.window.backgroundColor = [UIColor whiteColor];
    
    return YES;
}

2. 运行结果



3. 分析



1)当触摸紫色视图(LHSubview)时,因为 LHSubview 实现了 touchesBegin:withEvent: 方法,所以由 LHSubview 处理事件,并不会再向其 nextResponder 对象传递;如果 LHSubview 没有实现 touchesBegin:withEvent: 方法,就会向其 nextResponder 对象传递该方法,直至 UIApplication 类
2)当触摸橙色视图(LHMainView)时,因为触摸的是 LHMainView 对象,所以就从该对象开始查找事件方法,不会再向其 子视图搜索
3)因为代码中的 touchesBegin:withEvent: 方法中都添加了向其 nextResponder 对象发送 touchesBegin:withEvent:  方法的代码,所以,如果触摸紫色视图,则会从紫色视图开始至 UIApplication,中间的所有对象都会执行 touchesBegin:withEvent:  方法,结果如下





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值