在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;
}
@end
UIView默认不允许设置为第一响应者,因此设置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)启动接受远程事件