ios開發 之 UIResponder詳解
阿新 • • 發佈:2019-02-16
在iOS中UIResponder類是專門用來響應使用者的操作處理各種事件的,包括觸控事件(Touch Events)、運動事件(Motion Events)、遠端控制事件(Remote Control Events)。我們知道UIApplication、UIView、UIViewController這幾個類是直接繼承自UIResponder,所以這些類都可以響應事件。當然我們自定義的繼承自UIView的View以及自定義的繼承自UIViewController的控制器都可以響應事件。本文將詳細介紹UIResponder類。
一、使用詳解
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、設定與取消第一響應者
UIView預設不允許設定為第一響應者,因此設定UIView為第一響應者需要重寫canBecomeFirstResponder方法並返回YES。 設定為第一響應者後,物件則可以接受遠端控制事件進行處理(如耳機線控)。UITextField、UITextView成為第一響應者後會彈出輸入鍵盤,取消第一響應者則會隱藏輸入鍵盤。// // 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
為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);
@end
NS_ASSUME_NONNULL_END
原文地址:http://blog.csdn.net/zeng_zhiming/article/details/71747881