您的位置:首页 > 移动开发 > IOS开发

iOS——事件响应链

2017-03-26 15:57 441 查看

一、原理

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:
 方法,结果如下

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ios 事件响应链