在iOS中UIResponder类是专门用来响应用户的操作处理各种事件的,包括触摸事件(Touch Events)、运动事件(Motion Events)、远程控制事件(Remote Control Events)。我们知道UIApplication、UIView、UIViewController这几个类是直接继承自UIResponder,所以这些类都可以响应事件。当然我们自定义的继承自UIView的View以及自定义的继承自UIViewController的控制器都可以响应事件。本文将详细介绍UIResponder类。
原文地址:http://blog.youkuaiyun.com/zeng_zhiming/article/details/71747881
一、使用详解
1、通过响应者链查找视图的视图控制器
- /**
- * 查找视图的视图控制器
- *
- * @param view 视图
- *
- * @return 返回视图的控制器
- */
- - (UIViewController *)getControllerFromView:(UIView *)view {
- // 遍历响应者链。返回第一个找到视图控制器
- UIResponder *responder = view;
- while ((responder = [responder nextResponder])){
- if ([responder isKindOfClass: [UIViewController class]]){
- return (UIViewController *)responder;
- }
- }
- // 如果没有找到则返回nil
- return nil;
- }
通过响应链查找视图控制器,nextResponder获取下一个响应者,响应者顺序为:
2、设置与取消第一响应者
- //
- // ZMFirstResponderView.m
- // ZMResponderDemo
- //
- // Created by ZengZhiming on 2017/5/12.
- // Copyright © 2017年 菜鸟基地. All rights reserved.
- //
- #import "ZMFirstResponderView.h"
- @implementation ZMFirstResponderView
- /** 演示设置为第一响应者 */
- - (void)setBecomeFirstResponder {
- // 判断对象是否已经是第一响应者
- if ([self isFirstResponder]) {
- return;
- }
- // 判断对象是否允许成为第一响应者
- if ([self canBecomeFirstResponder]) {
- // 设置成为第一响应者
- [self becomeFirstResponder];
- }
- }
- /** 演示放弃第一响应者 */
- - (void)setResignFirstResponder {
- // 判断对象是否不是第一响应者
- if (![self isFirstResponder]) {
- return;
- }
- // 判断对象是否允许放弃第一响应者
- if ([self canResignFirstResponder]) {
- // 设置放弃第一响应者
- [self resignFirstResponder];
- }
- }
- /** 重写方法,允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
- @end
3、触摸相关方法,一般用于响应屏幕触摸
- /** 手指按下时响应 */
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
- [super touchesBegan:touches withEvent:event];
- NSLog(@"--->手指按下时响应");
- }
- /** 手指移动时响应 */
- - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
- [super touchesMoved:touches withEvent:event];
- NSLog(@"--->手指移动时响应");
- }
- /** 手指抬起时响应 */
- - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
- [super touchesEnded:touches withEvent:event];
- NSLog(@"--->手指抬起时响应");
- }
- /** 触摸取消(意外中断, 如:电话, Home键退出等) */
- - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event {
- [super touchesCancelled:touches withEvent:event];
- NSLog(@"--->取消触摸响应");
- }
4、加速相关方法,一般用于摇一摇、运动事件监听等
- /** 开始加速 */
- - (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0) {
- [super motionBegan:motion withEvent:event];
- NSLog(@"--->开始加速");
- }
- /** 结束加速 */
- - (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0) {
- [super motionEnded:motion withEvent:event];
- NSLog(@"--->结束加速");
- }
- /** 加速取消(意外中断, 如:电话, Home键退出等) */
- - (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0) {
- [super motionCancelled:motion withEvent:event];
- NSLog(@"--->加速取消");
- }
5、远程控制方法,一般用于耳机线控
- //
- // ZMAudioView.m
- // ZMResponderDemo
- //
- // Created by ZengZhiming on 2017/5/12.
- // Copyright © 2017年 菜鸟基地. All rights reserved.
- //
- #import "ZMAudioView.h"
- #import <AVFoundation/AVFoundation.h>
- @implementation ZMAudioView
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- // 启动接受远程事件
- [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
- // 设置成为第一响应者
- [self becomeFirstResponder];
- // 播放一段静音文件,使APP获取音频的控制权
- NSURL *audioURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"mute_60s" ofType:@"mp3"]];
- AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
- [audioPlayer play];
- }
- return self;
- }
- /** 允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
- /** 远程控制事件响应 */
- - (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
- NSLog(@"--->耳机线控响应");
- }
- - (void)dealloc {
- // 停止接受远程事件
- [[UIApplication sharedApplication] endReceivingRemoteControlEvents];
- // 放弃第一响应者
- [self resignFirstResponder];
- }
- @end
耳机线控要注意三点要素:
(1)启动接受远程事件:[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
(2)设置成为第一响应者(UIViewController,AppDelegate中不需要设置)
- // 设置成为第一响应者
- [self becomeFirstResponder];
- /** 允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
(3)获取音频的控制权
- // 播放一段静音文件,使APP获取音频的控制权
- NSURL *audioURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"mute_60s" ofType:@"mp3"]];
- AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
- [audioPlayer play];
6、在UILabel中实现长按菜单(复制、粘贴等)
- //
- // ZMMenuLabel.m
- // ZMResponderDemo
- //
- // Created by ZengZhiming on 2017/5/15.
- // Copyright © 2017年 菜鸟基地. All rights reserved.
- //
- #import "ZMMenuLabel.h"
- @implementation ZMMenuLabel
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- // 启用用户交互
- self.userInteractionEnabled = YES;
- // 添加长按手势
- UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMenu:)];
- longPressGesture.minimumPressDuration = 0.2;
- [self addGestureRecognizer:longPressGesture];
- }
- return self;
- }
- /** 允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
- /** 长按响应 */
- - (void)longPressMenu:(UILongPressGestureRecognizer *)sender {
- if (sender.state == UIGestureRecognizerStateBegan) {
- // 设置成为第一响应者
- [self becomeFirstResponder];
- // 显示菜单
- UIMenuController *menuCtrl = [UIMenuController sharedMenuController];
- [menuCtrl setTargetRect:self.frame inView:self.superview];
- [menuCtrl setMenuVisible:YES animated:YES];
- }
- }
- /** 返回需要显示的菜单按钮 */
- - (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
- // 只显示复制、粘贴按钮
- if (action == @selector(copy:) || action == @selector(paste:)) {
- return YES;
- }
- return NO;
- }
- /** 实现复制方法 */
- - (void)copy:(id)sender {
- UIPasteboard *paste = [UIPasteboard generalPasteboard];
- paste.string = self.text;
- }
- /** 实现粘贴方法 */
- - (void)paste:(id)sender {
- UIPasteboard *paste = [UIPasteboard generalPasteboard];
- self.text = paste.string;
- }
- @end
(1)启用用户交互:self.userInteractionEnabled = YES;
(2)在显示菜单之前设置对象成为第一响应者(UIViewController,AppDelegate中不需要设置)
- /** 允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
- // 设置成为第一响应者
- [self becomeFirstResponder];
(3)返回菜单需要显示的按钮,并重写实现对应方法
- /** 返回需要显示的菜单按钮 */
- - (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
- // 只显示复制、粘贴按钮
- if (action == @selector(copy:) || action == @selector(paste:)) {
- return YES;
- }
- return NO;
- }
- /** 实现复制方法 */
- - (void)copy:(id)sender {
- UIPasteboard *paste = [UIPasteboard generalPasteboard];
- paste.string = self.text;
- }
- /** 实现粘贴方法 */
- - (void)paste:(id)sender {
- UIPasteboard *paste = [UIPasteboard generalPasteboard];
- self.text = paste.string;
- }
- // 添加长按手势
- UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMenu:)];
- longPressGesture.minimumPressDuration = 0.2;
- [self addGestureRecognizer:longPressGesture];
- /** 长按响应 */
- - (void)longPressMenu:(UILongPressGestureRecognizer *)sender {
- if (sender.state == UIGestureRecognizerStateBegan) {
- // 设置成为第一响应者
- [self becomeFirstResponder];
- // 显示菜单
- UIMenuController *menuCtrl = [UIMenuController sharedMenuController];
- [menuCtrl setTargetRect:self.frame inView:self.superview];
- [menuCtrl setMenuVisible:YES animated:YES];
- }
- }
7、使用NSUndoManager实现画板撤销/重做功能
- /** ==============ZMDrawingBoardView.h文件=================== */
- #import <UIKit/UIKit.h>
- /** 画板View */
- @interface ZMDrawingBoardView : UIView
- @end
- /** 划线Model */
- @interface ZMLineModel : NSObject
- @property (nonatomic) CGPoint begin;
- @property (nonatomic) CGPoint end;
- @end
- /** ==============ZMDrawingBoardView.m文件=================== */
- #import "ZMDrawingBoardView.h"
- /** 画板View */
- @interface ZMDrawingBoardView ()
- @property (nonatomic, strong) ZMLineModel *currentLine;
- @property (nonatomic, strong) NSMutableArray<ZMLineModel *> *toucheArray;
- @end
- @implementation ZMDrawingBoardView
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- [self initSubView];
- self.backgroundColor = [UIColor whiteColor];
- self.toucheArray = [NSMutableArray array];
- }
- return self;
- }
- /** 绘制画板 */
- - (void)drawRect:(CGRect)rect {
- // 获得上下文
- CGContextRef context = UIGraphicsGetCurrentContext();
- // 设置样式
- CGContextSetLineCap(context, kCGLineCapSquare);
- // 设置宽度
- CGContextSetLineWidth(context, 5.0);
- // 设置颜色
- CGContextSetStrokeColorWithColor(context, [[UIColor redColor] CGColor]);
- for (ZMLineModel *line in self.toucheArray) {
- // 开始绘制
- CGContextBeginPath(context);
- // 移动画笔到起点
- CGContextMoveToPoint(context, line.begin.x, line.begin.y);
- // 添加下一点
- CGContextAddLineToPoint(context, line.end.x, line.end.y);
- // 绘制完成
- CGContextStrokePath(context);
- }
- }
- /** 划线开始 */
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- // 标记开始撤销分组
- [self.undoManager beginUndoGrouping];
- for (UITouch *touch in touches) {
- // 记录起始点
- CGPoint locTouch = [touch locationInView:self];
- _currentLine = [[ZMLineModel alloc] init];
- _currentLine.begin = locTouch;
- _currentLine.end = locTouch;
- }
- }
- /** 划线移动 */
- - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
- {
- for (UITouch *touch in touches) {
- // 添加线条
- CGPoint locTouch = [touch locationInView:self];
- _currentLine.end = locTouch;
- [self addLine:_currentLine];
- // 当前线条
- _currentLine = [[ZMLineModel alloc] init];
- _currentLine.begin = locTouch;
- _currentLine.end = locTouch;
- }
- }
- /** 划线结束 */
- - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- {
- // 结束标记撤销分组
- [self.undoManager endUndoGrouping];
- }
- /** 添加划线 */
- - (void)addLine:(ZMLineModel *)line
- {
- // 添加划线并重绘画板
- [self.toucheArray addObject:line];
- [self setNeedsDisplay];
- // 注册撤销方法
- [[self.undoManager prepareWithInvocationTarget:self] removeLine:line];
- }
- /** 移除划线 */
- - (void)removeLine:(ZMLineModel *)line
- {
- if ([self.toucheArray containsObject:line]) {
- // 移除划线并重绘画板
- [self.toucheArray removeObject:line];
- [self setNeedsDisplay];
- // 注册撤销方法
- [[self.undoManager prepareWithInvocationTarget:self] addLine:line];
- }
- }
- /** 撤销按钮点击响应 */
- - (void)undoButtonAction:(id)sender {
- if ([self.undoManager canUndo]) {
- [self.undoManager undo];
- }
- }
- /** 重做按钮点击响应 */
- - (void)redoButtonAction:(id)sender {
- if ([self.undoManager canRedo]) {
- [self.undoManager redo];
- }
- }
- /** 初始化子控件 */
- - (void)initSubView {
- // 撤销按钮
- UIButton *undoButton = [UIButton buttonWithType:UIButtonTypeSystem];
- undoButton.frame = CGRectMake(0, 64, 70, 50);
- [undoButton setTitle:@"undo撤销" forState:UIControlStateNormal];
- [undoButton sizeToFit];
- [undoButton addTarget:self action:@selector(undoButtonAction:) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:undoButton];
- // 重做按钮
- UIButton *redoButton = [UIButton buttonWithType:UIButtonTypeSystem];
- redoButton.frame = CGRectMake(CGRectGetWidth(self.frame)-70, 64, 70, 50);
- [redoButton setTitle:@"redo重做" forState:UIControlStateNormal];
- [redoButton sizeToFit];
- [redoButton addTarget:self action:@selector(redoButtonAction:) forControlEvents:UIControlEventTouchUpInside];
- [self addSubview:redoButton];
- }
- @end
(1)在调用方法时需要添加注册一个对应的撤销方法
- // 注册撤销方法
- [[self.undoManager prepareWithInvocationTarget:self] removeLine:line];
- /** 撤销按钮点击响应 */
- - (void)undoButtonAction:(id)sender {
- if ([self.undoManager canUndo]) {
- [self.undoManager undo];
- }
- }
- /** 重做按钮点击响应 */
- - (void)redoButtonAction:(id)sender {
- if ([self.undoManager canRedo]) {
- [self.undoManager redo];
- }
- }
- // 标记开始撤销分组
- [self.undoManager beginUndoGrouping];
- // 结束标记撤销分组
- [self.undoManager endUndoGrouping];
8、自定义快捷键
- //
- // ZMKeyCommandView.m
- // ZMResponderDemo
- //
- // Created by ZengZhiming on 2017/5/17.
- // Copyright © 2017年 菜鸟基地. All rights reserved.
- //
- #import "ZMKeyCommandView.h"
- @implementation ZMKeyCommandView
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- // 设置成为第一响应者
- [self becomeFirstResponder];
- }
- return self;
- }
- /** 允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
- /** 返回快捷命令数组 */
- -(NSArray<UIKeyCommand *> *)keyCommands {
- return @[
- [UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:UIKeyModifierShift action:@selector(pressedShiftAndEscapeKey:) discoverabilityTitle:@"自定义[Shift+Esc]快捷键"],
- [UIKeyCommand keyCommandWithInput:@"a" modifierFlags:UIKeyModifierShift action:@selector(pressedShiftAndAKey:) discoverabilityTitle:@"自定义[Shift+A]快捷键"]
- ];
- }
- /** Shift+Esc快捷命令响应 */
- -(void)pressedShiftAndEscapeKey:(UIKeyCommand *)keyCommand {
- UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:keyCommand.discoverabilityTitle message:[NSString stringWithFormat:@"按下快捷辅键:[%@]", keyCommand.input] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
- [alertView show];
- }
- /** Shift+A快捷命令响应 */
- -(void)pressedShiftAndAKey:(UIKeyCommand *)keyCommand {
- UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:keyCommand.discoverabilityTitle message:[NSString stringWithFormat:@"按下快捷辅键:[%@]", keyCommand.input] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
- [alertView show];
- }
- @end
(1)设置对象成为第一响应者(UIViewController,AppDelegate中不需要设置)
- // 设置成为第一响应者
- [self becomeFirstResponder];
- /** 允许对象成为第一响应者 */
- - (BOOL)canBecomeFirstResponder {
- return YES;
- }
- /** 返回快捷命令数组 */
- -(NSArray<UIKeyCommand *> *)keyCommands {
- return @[
- [UIKeyCommand keyCommandWithInput:UIKeyInputEscape modifierFlags:UIKeyModifierShift action:@selector(pressedShiftAndEscapeKey:) discoverabilityTitle:@"自定义[Shift+Esc]快捷键"],
- [UIKeyCommand keyCommandWithInput:@"a" modifierFlags:UIKeyModifierShift action:@selector(pressedShiftAndAKey:) discoverabilityTitle:@"自定义[Shift+A]快捷键"]
- ];
- }
9、自定义UITextField输入键盘
- //
- // ZMCustomInputView.m
- // ZMResponderDemo
- //
- // Created by ZengZhiming on 2017/5/18.
- // Copyright © 2017年 菜鸟基地. All rights reserved.
- //
- #import "ZMCustomInputView.h"
- #define MAIN_SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width //!< 屏幕的Width
- @interface ZMCustomInputView ()
- @property (nonatomic, strong) UITextField *textField;
- @property (nonatomic, strong) UIView *customInputView;
- @property (nonatomic, strong) UIToolbar *customAccessoryView;
- @end
- @implementation ZMCustomInputView
- - (instancetype)initWithFrame:(CGRect)frame
- {
- self = [super initWithFrame:frame];
- if (self) {
- // 添加TextField
- [self addSubview:self.textField];
- }
- return self;
- }
- /** 懒加载textField */
- - (UITextField *)textField {
- if (!_textField) {
- // 初始化textField
- _textField = [[UITextField alloc]initWithFrame:CGRectMake(50, 100, MAIN_SCREEN_WIDTH - 100, 30)];
- _textField.borderStyle = UITextBorderStyleRoundedRect;
- _textField.placeholder = @"测试";
- // 设置自定义键盘View
- _textField.inputView = self.customInputView;
- _textField.inputAccessoryView = self.customAccessoryView;
- }
- return _textField;
- }
- /** 懒加载customInputView */
- - (UIView *)customInputView {
- if (!_customInputView) {
- _customInputView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, MAIN_SCREEN_WIDTH, 220)];
- _customInputView.backgroundColor = [UIColor lightGrayColor];
- UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, MAIN_SCREEN_WIDTH, 40)];
- label.textAlignment = NSTextAlignmentCenter;
- label.text = @"自定义inputView";
- [_customInputView addSubview:label];
- }
- return _customInputView;
- }
- /** 懒加载customAccessoryView */
- - (UIToolbar *)customAccessoryView {
- if (!_customAccessoryView) {
- _customAccessoryView = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, MAIN_SCREEN_WIDTH, 40)];
- _customAccessoryView.barTintColor = [UIColor orangeColor];
- UIBarButtonItem *space = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
- UIBarButtonItem *done = [[UIBarButtonItem alloc]initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(done)];
- [_customAccessoryView setItems:@[space, space, done]];
- }
- return _customAccessoryView;
- }
- /** 响应完成按钮 */
- - (void)done {
- [self.textField resignFirstResponder];
- }
- @end
二、UIResponder.h详解
- //
- // UIResponder.h
- // ZMHeaderFile
- //
- // Created by ZengZhiming on 2017/4/18.
- // Copyright © 2017年 菜鸟基地. All rights reserved.
- //
- // 详解 UIResponder.h
- // Version iOS 10.3
- //
- #import <Foundation/Foundation.h>
- #import <UIKit/UIKitDefines.h>
- #import <UIKit/UIEvent.h>
- NS_ASSUME_NONNULL_BEGIN
- @class UIPress;
- @class UIPressesEvent;
- #pragma mark - UIResponderStandardEditActions协议定义
- @protocol UIResponderStandardEditActions <NSObject>
- @optional
- /** 剪切事件 */
- - (void)cut:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- /** 复制事件 */
- - (void)copy:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- /** 粘贴事件 */
- - (void)paste:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- /** 选择事件 */
- - (void)select:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- /** 全选事件 */
- - (void)selectAll:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- /** 删除事件 */
- - (void)delete:(nullable id)sender NS_AVAILABLE_IOS(3_2);
- /** 从左到右写入字符串(居左) */
- - (void)makeTextWritingDirectionLeftToRight:(nullable id)sender NS_AVAILABLE_IOS(5_0);
- /** 从右到左写入字符串(居右) */
- - (void)makeTextWritingDirectionRightToLeft:(nullable id)sender NS_AVAILABLE_IOS(5_0);
- /** 切换字体为黑体(粗体) */
- - (void)toggleBoldface:(nullable id)sender NS_AVAILABLE_IOS(6_0);
- /** 切换字体为斜体 */
- - (void)toggleItalics:(nullable id)sender NS_AVAILABLE_IOS(6_0);
- /** 给文字添加下划线 */
- - (void)toggleUnderline:(nullable id)sender NS_AVAILABLE_IOS(6_0);
- /** 增加字体大小 */
- - (void)increaseSize:(nullable id)sender NS_AVAILABLE_IOS(7_0);
- /** 减小字体大小 */
- - (void)decreaseSize:(nullable id)sender NS_AVAILABLE_IOS(7_0);
- @end
- #pragma mark - UIResponder类定义
- NS_CLASS_AVAILABLE_IOS(2_0) @interface UIResponder : NSObject <UIResponderStandardEditActions>
- #pragma mark - 响应者相关方法
- /** 获取下一个响应者 */
- #if UIKIT_DEFINE_AS_PROPERTIES
- @property(nonatomic, readonly, nullable) UIResponder *nextResponder;
- #else
- - (nullable UIResponder *)nextResponder;
- #endif
- /** 是否允许成为第一响应者。默认返回NO */
- #if UIKIT_DEFINE_AS_PROPERTIES
- @property(nonatomic, readonly) BOOL canBecomeFirstResponder;
- #else
- - (BOOL)canBecomeFirstResponder;
- #endif
- /** 设置成为第一响应者 */
- - (BOOL)becomeFirstResponder;
- /** 是否允许放弃第一响应者。默认返回YES */
- #if UIKIT_DEFINE_AS_PROPERTIES
- @property(nonatomic, readonly) BOOL canResignFirstResponder;
- #else
- - (BOOL)canResignFirstResponder;
- #endif
- /** 设置放弃第一响应者 */
- - (BOOL)resignFirstResponder;
- /** 判断对象是否是第一响应者 */
- #if UIKIT_DEFINE_AS_PROPERTIES
- @property(nonatomic, readonly) BOOL isFirstResponder;
- #else
- - (BOOL)isFirstResponder;
- #endif
- #pragma mark - 触摸相关方法,一般用于响应屏幕触摸
- /** 手指按下时响应 */
- - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- /** 手指移动时响应 */
- - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- /** 手指抬起时响应 */
- - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- /** 取消(意外中断, 如:电话, 系统警告窗等) */
- - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- /** 3DTouch响应(iOS9.1后使用) */
- - (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);
- #pragma mark - 深按相关方法,一般用于遥控器按键响应
- /** 手指按压开始时响应 */
- - (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- /** 手指按压位置移动时响应 */
- - (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- /** 手指抬起接受按压时响应 */
- - (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- /** 按压取消(意外中断, 如:电话, 系统警告窗等) */
- - (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);
- #pragma mark - 加速相关方法,一般用于摇一摇、运动事件监听等
- /** 开始加速 */
- - (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
- /** 结束加速 */
- - (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
- /** 加速取消(意外中断, 如:电话, 系统警告窗等) */
- - (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
- /** 远程控制事件 */
- - (void)remoteControlReceivedWithEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(4_0);
- /** 返回UIMenuController需要显示的控件(如:复制,粘贴等) */
- - (BOOL)canPerformAction:(SEL)action withSender:(nullable id)sender NS_AVAILABLE_IOS(3_0);
- /** 返回响应的操作目标对象 */
- - (nullable id)targetForAction:(SEL)action withSender:(nullable id)sender NS_AVAILABLE_IOS(7_0);
- /** 获取响应链就近共享撤消管理 */
- @property(nullable, nonatomic,readonly) NSUndoManager *undoManager NS_AVAILABLE_IOS(3_0);
- @end
- /** 快捷主键枚举 */
- typedef NS_OPTIONS(NSInteger, UIKeyModifierFlags) {
- UIKeyModifierAlphaShift = 1 << 16, //!< Alpha+Shift键.
- UIKeyModifierShift = 1 << 17, //!< Shift键.
- UIKeyModifierControl = 1 << 18, //!< Control键.
- UIKeyModifierAlternate = 1 << 19, //!< Alt键.
- UIKeyModifierCommand = 1 << 20, //!< Command键.
- UIKeyModifierNumericPad = 1 << 21, //!< Num键.
- } NS_ENUM_AVAILABLE_IOS(7_0);
- #pragma mark - 快捷键对象
- NS_CLASS_AVAILABLE_IOS(7_0) @interface UIKeyCommand : NSObject <NSCopying, NSSecureCoding>
- /** 初始化对象 */
- - (instancetype)init NS_DESIGNATED_INITIALIZER;
- /** 初始化对象 */
- - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
- /** 获取快捷辅键(如快捷命令【Command+A】中的 A 键) */
- @property (nonatomic,readonly) NSString *input;
- /** 获取快捷主键(如快捷命令【Command+A】中的 Command 键) */
- @property (nonatomic,readonly) UIKeyModifierFlags modifierFlags;
- /** 显示给用户的快捷键标题 */
- @property (nullable,nonatomic,copy) NSString *discoverabilityTitle NS_AVAILABLE_IOS(9_0);
- /** 创建一个快捷键命令 */
- + (UIKeyCommand *)keyCommandWithInput:(NSString *)input modifierFlags:(UIKeyModifierFlags)modifierFlags action:(SEL)action;
- /** 创建一个快捷键命令 */
- + (UIKeyCommand *)keyCommandWithInput:(NSString *)input modifierFlags:(UIKeyModifierFlags)modifierFlags action:(SEL)action discoverabilityTitle:(NSString *)discoverabilityTitle NS_AVAILABLE_IOS(9_0);
- @end
- #pragma mark - 响应快捷命令
- @interface UIResponder (UIResponderKeyCommands)
- /** 返回快捷键命令数组 */
- @property (nullable,nonatomic,readonly) NSArray<UIKeyCommand *> *keyCommands NS_AVAILABLE_IOS(7_0);
- @end
- @class UIInputViewController;
- @class UITextInputMode;
- @class UITextInputAssistantItem;
- #pragma mark - 输入视图
- @interface UIResponder (UIResponderInputViewAdditions)
- /** 键盘输入视图(系统默认的,可以自定义) */
- @property (nullable, nonatomic, readonly, strong) __kindof UIView *inputView NS_AVAILABLE_IOS(3_2);
- /** 弹出键盘时附带的视图 */
- @property (nullable, nonatomic, readonly, strong) __kindof UIView *inputAccessoryView NS_AVAILABLE_IOS(3_2);
- /** 输入助手配置键盘的快捷方式栏时使用 */
- @property (nonnull, nonatomic, readonly, strong) UITextInputAssistantItem *inputAssistantItem NS_AVAILABLE_IOS(9_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED;
- /** 键盘输入视图控制器 */
- @property (nullable, nonatomic, readonly, strong) UIInputViewController *inputViewController NS_AVAILABLE_IOS(8_0);
- /** 弹出键盘时附带的视图的视图控制器 */
- @property (nullable, nonatomic, readonly, strong) UIInputViewController *inputAccessoryViewController NS_AVAILABLE_IOS(8_0);
- /** 文本输入模式 */
- @property (nullable, nonatomic, readonly, strong) UITextInputMode *textInputMode NS_AVAILABLE_IOS(7_0);
- /** 文本输入模式标识 */
- @property (nullable, nonatomic, readonly, strong) NSString *textInputContextIdentifier NS_AVAILABLE_IOS(7_0);
- /** 根据设置的标识清除指定的文本输入模式 */
- + (void)clearTextInputContextIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(7_0);
- /** 重新刷新键盘输入视图 */
- - (void)reloadInputViews NS_AVAILABLE_IOS(3_2);
- @end
- /** 特殊快捷辅键定义 */
- UIKIT_EXTERN NSString *const UIKeyInputUpArrow NS_AVAILABLE_IOS(7_0); //!< 上按键.
- UIKIT_EXTERN NSString *const UIKeyInputDownArrow NS_AVAILABLE_IOS(7_0); //!< 下按键.
- UIKIT_EXTERN NSString *const UIKeyInputLeftArrow NS_AVAILABLE_IOS(7_0); //!< 左按键.
- UIKIT_EXTERN NSString *const UIKeyInputRightArrow NS_AVAILABLE_IOS(7_0); //!< 右按键
- UIKIT_EXTERN NSString *const UIKeyInputEscape NS_AVAILABLE_IOS(7_0); //!< Esc按键.
- #pragma mark - 响应者活动
- @interface UIResponder (ActivityContinuation)
- /** 用户活动 */
- @property (nullable, nonatomic, strong) NSUserActivity *userActivity NS_AVAILABLE_IOS(8_0);
- /** 更新用户活动 */
- - (void)updateUserActivityState:(NSUserActivity *)activity NS_AVAILABLE_IOS(8_0);
- /** 恢复用户活动 */
- - (void)restoreUserActivityState:(NSUserActivity *)activity NS_AVAILABLE_IOS(8_0);
- @end
- NS_ASSUME_NONNULL_END
Demo地址:https://github.com/zeng-zhiming/ZMResponderDemo