ios开发 之 UIResponder详解
来源:互联网 发布:badusb淘宝 编辑:程序博客网 时间:2024/06/05 15:59
在iOS中UIResponder类是专门用来响应用户的操作处理各种事件的,包括触摸事件(Touch Events)、运动事件(Motion Events)、远程控制事件(Remote Control Events)。我们知道UIApplication、UIView、UIViewController这几个类是直接继承自UIResponder,所以这些类都可以响应事件。当然我们自定义的继承自UIView的View以及自定义的继承自UIViewController的控制器都可以响应事件。本文将详细介绍UIResponder类。
原文地址:http://blog.csdn.net/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;}@endUIView默认不允许设置为第一响应者,因此设置UIView为第一响应者需要重写canBecomeFirstResponder方法并返回YES。 设置为第一响应者后,对象则可以接受远程控制事件进行处理(如耳机线控)。UITextField、UITextView成为第一响应者后会弹出输入键盘,取消第一响应者则会隐藏输入键盘。
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为UILabel添加长按菜单需要注意几点:
(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;}(4)注册长按手势,显示菜单
// 添加长按手势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];(2)撤销/ 重做只需要调用undoManager中的相应方法即可
/** 撤销按钮点击响应 */- (void)undoButtonAction:(id)sender { if ([self.undoManager canUndo]) { [self.undoManager undo]; }}/** 重做按钮点击响应 */- (void)redoButtonAction:(id)sender { if ([self.undoManager canRedo]) { [self.undoManager redo]; }}(3)如果需要多个动作一起撤销则需要标记分组
// 标记开始撤销分组 [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;}(2)重写keyCommands返回快捷命令组合
/** 返回快捷命令数组 */-(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);@endNS_ASSUME_NONNULL_END
Demo地址:https://github.com/zeng-zhiming/ZMResponderDemo
- ios开发 之 UIResponder详解
- IOS开发笔记-UIResponder
- iOS控件之UIResponder
- iOS控件之UIResponder
- iOS控件之UIResponder
- iOS开发中的事件处理(一)-UIResponder-
- UIResponder详解
- UIResponder详解
- UIResponder 详解
- UIResponder详解
- UIResponder详解
- IOS学习之——UIResponder
- iOS开发 UI 加深理解UIView,UIResponder,UIController
- iOS框架研究 之 UIResponder 可以接收事件的对象
- iOS UIResponder 学习笔记
- UIResponder 对象详解
- UIResponder使用详解
- UIResponder 对象详解
- 百度搜索引擎工作原理
- VS生成解决方案成功,运行页面时提示:[3000]尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
- Unity ScriptableObject初探
- Unity3D 发布成PC端常用设置
- Python中对两种utf-8格式的理解
- ios开发 之 UIResponder详解
- 安卓自定义标题栏
- Ubuntu下配置samba实现文件夹共享
- 面试系列(四)
- jsonp 读取本地文件
- AOJ.870 MAX 的读书计划
- 逆向
- mongoDBChef连接不上CentOS上的mongodb
- [docker]你不知道的docker奇淫技巧