UIEvent
A UIEvent object (or, simply, an event object) represents an event in iOS. There are three general types of event: **touch events, motion events, and remote-control events ** Remote-control events allow a responder object to receive commands from an external accessory or headset so that it can manage manage audio and video—for example, playing a video or skipping to the next audio track. Motion events were introduced in iOS 3.0 and remote-control events in iOS 4.0.
Overview
A touch type of event object contains one or more touches (that is, finger gestures on the screen) that have some relation to the event. A touch is represented by a UITouch object. When a touch event occurs, the system routes it to the appropriate responder and passes in the UIEvent object in a message invoking a UIResponder method such as touchesBegan:withEvent:. The responder can then evaluate the touches for the event or for a particular phase of the event and handle them appropriately. The methods of UIEvent allow you to obtain all touches for the event (allTouches) or only those for a given view or window (touchesForView: or touchesForWindow:). It can also distinguish an event object from objects representing other events by querying an object for the time of its creation (timestamp).
A UIEvent object representing a touch event is persistent throughout a multi-touch sequence; UIKit reuses the same UIEvent instance for every event delivered to the application. You should never retain an event object or any object returned from an event object. If you need to keep information from an event around from one phase to another, you should copy that information from the UITouch or UIEvent object.
You can obtain event types and subtypes from the type and subtype properties. UIEvent defines event types for touch, motion, and remote-control events. It also defines a motion subtype for "shake” events and a series of subtype constants for remote-control events, such as “play” and “previous track.” The first responder or any responder in the responder chain implements the motion-related methods of UIResponder (such as motionBegan:withEvent:) to handle shaking-motion events. To handle remote-control events, a responder object must implement the remoteControlReceivedWithEvent: method of UIResponder.
The touchesForGestureRecognizer: method, which was introduced in iOS 3.2, allows you to query a gesture-recognizer object (an instance of a subclass of UIGestureRecognizer) for the touches it is currently handling.
typedef NS_ENUM(NSInteger, UIEventType) {
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),
};
typedef NS_ENUM(NSInteger, UIEventSubtype) {
// 不包含任何子事件類型
UIEventSubtypeNone = 0,
// 搖晃事件(從iOS3.0開(kāi)始支持此事件)
UIEventSubtypeMotionShake = 1,
//遠(yuǎn)程控制子事件類型(從iOS4.0開(kāi)始支持遠(yuǎn)程控制事件)
//播放事件【操作:停止?fàn)顟B(tài)下,按耳機(jī)線控中間按鈕一下】
UIEventSubtypeRemoteControlPlay = 100,
//暫停事件
UIEventSubtypeRemoteControlPause = 101,
//停止事件
UIEventSubtypeRemoteControlStop = 102,
//播放或暫停切換【操作:播放或暫停狀態(tài)下,按耳機(jī)線控中間按鈕一下】
UIEventSubtypeRemoteControlTogglePlayPause = 103,
//下一曲【操作:按耳機(jī)線控中間按鈕兩下】
UIEventSubtypeRemoteControlNextTrack = 104,
//上一曲【操作:按耳機(jī)線控中間按鈕三下】
UIEventSubtypeRemoteControlPreviousTrack = 105,
//快退開(kāi)始【操作:按耳機(jī)線控中間按鈕三下不要松開(kāi)】
UIEventSubtypeRemoteControlBeginSeekingBackward = 106,
//快退停止【操作:按耳機(jī)線控中間按鈕三下到了快退的位置松開(kāi)】
UIEventSubtypeRemoteControlEndSeekingBackward = 107,
//快進(jìn)開(kāi)始【操作:按耳機(jī)線控中間按鈕兩下不要松開(kāi)】
UIEventSubtypeRemoteControlBeginSeekingForward = 108,
//快進(jìn)停止【操作:按耳機(jī)線控中間按鈕兩下到了快進(jìn)的位置松開(kāi)】
UIEventSubtypeRemoteControlEndSeekingForward = 109,
};
@interface UIEvent : NSObject
@property(nonatomic,readonly) UIEventType type NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly) UIEventSubtype subtype NS_AVAILABLE_IOS(3_0);
@property(nonatomic,readonly) NSTimeInterval timestamp;
@property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches;
- (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;
- (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;
- (nullable NSSet <UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture NS_AVAILABLE_IOS(3_2);
// An array of auxiliary UITouch’s for the touch events that did not get delivered for a given main touch. This also includes an auxiliary version of the main touch itself.
- (nullable NSArray <UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch NS_AVAILABLE_IOS(9_0);
// An array of auxiliary UITouch’s for touch events that are predicted to occur for a given main touch. These predictions may not exactly match the real behavior of the touch as it moves, so they should be interpreted as an estimate.
- (nullable NSArray <UITouch *> *)predictedTouchesForTouch:(UITouch *)touch NS_AVAILABLE_IOS(9_0);
Shake to play systemSound using AudioToolBox.framework
static void AudioServicesSystemSoundCompletionCall(SystemSoundID ssID, void* __nullable clientData){
NSLog(@"聲音播放完成");
}
-(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
NSLog(@"搖動(dòng)開(kāi)始");
//播放文件路徑
NSString *pathStr = [[NSBundle mainBundle]pathForResource:@"59" ofType:@"m4a"];
NSURL *sourURL = [NSURL fileURLWithPath:pathStr];
//注冊(cè)系統(tǒng)音頻ID
SystemSoundID soundId;
AudioServicesCreateSystemSoundID((__bridge CFURLRef)sourURL, &soundId);
// AudioServicesPlaySystemSoundWithCompletion(soundId, ^{
// AudioServicesDisposeSystemSoundID(soundId);
// });
//or
AudioServicesAddSystemSoundCompletion(soundId, NULL, NULL, AudioServicesSystemSoundCompletionCall, (__bridge void *)self);
AudioServicesPlaySystemSound(soundId);
}
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
NSLog(@"搖動(dòng)結(jié)束");
}
-(void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{
if (event.subtype == UIEventSubtypeMotionShake) {
NSLog(@"搖動(dòng)取消");
}
}
RemoteControlEvents
//為了模擬一個(gè)真實(shí)的播放器,程序中我們啟用了后臺(tái)運(yùn)行模式,配置方法:在info.plist中添加UIBackgroundModes并且添加一個(gè)元素值為audio。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
if(![[AVAudioSession sharedInstance] setActive:YES error:nil])
{
NSLog(@"Failed to set up a session.");
}
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
// Override point for customization after application launch.
return YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
_player = [[AVPlayer alloc]initWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"小蘋(píng)果" ofType:@"mp3"]]];
[_player play];
}
#pragma mark =====3 線控
//配置方法:在info.plist中添加UIBackgroundModes并且添加一個(gè)元素值為audio。
-(BOOL)canBecomeFirstResponder{
return YES;
}
-(void)remoteControlReceivedWithEvent:(UIEvent *)event{
if (event.type == UIEventTypeRemoteControl) {
switch (event.subtype) {
case UIEventSubtypeRemoteControlPlay:{
NSLog(@"play---------");
}break;
case UIEventSubtypeRemoteControlPause:{
NSLog(@"Pause---------");
}break;
case UIEventSubtypeRemoteControlStop:{
NSLog(@"Stop---------");
}break;
case UIEventSubtypeRemoteControlTogglePlayPause:{
//單擊暫停鍵:103
NSLog(@"單擊暫停鍵:103");
static int a = 0;
a++;
if (a%2 == 1) {
[_player pause];
}else{
[_player play];
}
}break;
case UIEventSubtypeRemoteControlNextTrack:{
//雙擊暫停鍵:104
NSLog(@"雙擊暫停鍵:104");
}break;
case UIEventSubtypeRemoteControlPreviousTrack:{
NSLog(@"三擊暫停鍵:105");
}break;
case UIEventSubtypeRemoteControlBeginSeekingForward:{
NSLog(@"單擊,再按下不放:108");
}break;
case UIEventSubtypeRemoteControlEndSeekingForward:{
NSLog(@"單擊,再按下不放,松開(kāi)時(shí):109");
}break;
default:
break;
}
}
}
Insert earphone or pull out headphones
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:nil];//設(shè)置通知
}
//通知方法的實(shí)現(xiàn)
- (void)audioRouteChangeListenerCallback:(NSNotification*)notification
{
NSDictionary *interuptionDict = notification.userInfo;
NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
switch (routeChangeReason) {
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
NSLog(@"AVAudioSessionRouteChangeReasonNewDeviceAvailable");
tipWithMessage(@"耳機(jī)插入");
break;
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
NSLog(@"AVAudioSessionRouteChangeReasonOldDeviceUnavailable");
tipWithMessage(@"耳機(jī)拔出,停止播放操作");
break;
case AVAudioSessionRouteChangeReasonCategoryChange:
// called at start - also when other audio wants to play
tipWithMessage(@"AVAudioSessionRouteChangeReasonCategoryChange");
break;
}
}