Event programming guide

Phone中处理触摸屏的操作,在3.2之前是主要使用的是由UIResponder而来的如下4种方式:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
但是这种方式甄别不同的手势操作实在是麻烦,需要你自己计算做不同的手势分辨。后来。。。
苹果就给出了一个比较简便的方式,就是使用UIGestureRecognizer。

六种手势识别的class:
UITapGestureRecognizer
UIPinchGestureRecognizer
UIPanGestureRecognizer
UISwipeGestureRecognizer
UIRotationGestureRecognizer
UILongPressGestureRecognizer

点击手势响应
[img]http://dl.iteye.com/upload/attachment/0082/6989/4e7ecc92-a21a-3b46-aeb5-597763fed75f.png[/img]

单次响应和持续响应
[img]http://dl.iteye.com/upload/attachment/0082/6991/e2fcdbeb-7127-381c-9576-2b0f7a813eb0.png[/img]


//使用xib创建手势事件
@interface APLGestureRecognizerViewController ()
@property (nonatomic, strong) IBOutlet UITapGestureRecognizer *tapRecognizer;
@end
@implementation
- (IBAction)displayGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer
// Will implement method later...
}
@end

//通过代码创建
- (void)viewDidLoad {
[super viewDidLoad];
// Create and initialize a tap gesture
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(respondToTapGesture:)];
// Specify that the gesture must be a single tap
tapRecognizer.numberOfTapsRequired = 1;
// Add the tap gesture recognizer to the view
[self.view addGestureRecognizer:tapRecognizer];
// Do any additional setup after loading the view, typically from a nib
}
//处理双击事件响应的方法
- (IBAction)showGestureForTapRecognizer:(UITapGestureRecognizer *)recognizer {
// Get the location of the gesture
CGPoint location = [recognizer locationInView:self.view];
// Display an image view at that location
[self drawImageForGestureRecognizer:recognizer atPoint:location];
// Animate the image view so that it fades out
[UIView animateWithDuration:0.5 animations:^{
self.imageView.alpha = 0.0;
}]; }

//处理左移右移事件
// Respond to a swipe gesture
- (IBAction)showGestureForSwipeRecognizer:(UISwipeGestureRecognizer *)recognizer
{
}
// Get the location of the gesture
CGPoint location = [recognizer locationInView:self.view];
// Display an image view at that location
[self drawImageForGestureRecognizer:recognizer atPoint:location];
// If gesture is a left swipe, specify an end location
// to the left of the current location
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft) {
location.x -= 220.0;
} else {
location.x += 220.0;
}
// Animate the image view in the direction of the swipe as it fades out
[UIView animateWithDuration:0.5 animations:^{
self.imageView.alpha = 0.0;
self.imageView.center = location;
}];
//处理旋转事件
// Respond to a rotation gesture
- (IBAction)showGestureForRotationRecognizer:(UIRotationGestureRecognizer
*)recognizer {
// Get the location of the gesture
CGPoint location = [recognizer locationInView:self.view];
// Set the rotation angle of the image view to
// match the rotation of the gesture
CGAffineTransform transform = CGAffineTransformMakeRotation([recognizer
rotation]);
self.imageView.transform = transform;
// Display an image view at that location
[self drawImageForGestureRecognizer:recognizer atPoint:location];
// If the gesture has ended or is canceled, begin the animation
// back to horizontal and fade out
if (([recognizer state] == UIGestureRecognizerStateEnded) || ([recognizer
state] == UIGestureRecognizerStateCancelled)) {
[UIView animateWithDuration:0.5 animations:^{
self.imageView.alpha = 0.0;
self.imageView.transform = CGAffineTransformIdentity;
}]; }
}


手势识别几种状态的转化:
UIGestureRecognizerStateRecognized
UIGestureRecognizerStateBegan
UIGestureRecognizerStateChanged
UIGestureRecognizerStateEnded
UIGestureRecognizerStateCancelled
UIGestureRecognizerStateFailed
[img]http://dl.iteye.com/upload/attachment/0082/7158/1836b196-c75f-3144-95da-2cb83d92f1e3.png[/img]

如果在一个view上有多个手势,可以使用UIGestureRecognizer和它的delegate方法来处理。
手势识别是具有互斥的原则的,比如单击和双击,如果它识别出一种手势,其后的手势将不被识别。可以使用requireGestureRecognizerToFail:方法来取消手势


//Preventing a gesture recognizer from receiving a touch
- (void)viewDidLoad {
[super viewDidLoad];
// Add the delegate to the tap gesture recognizer
self.tapGestureRecognizer.delegate = self;
}
// Implement the UIGestureRecognizerDelegate method
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
// Determine if the touch is inside the custom subview
if ([touch view] == self.customSubview){
// If it is, prevent all of the delegate's gesture recognizers
// from receiving the touch
return NO;
}
return YES; }


允许同时手势识别:
gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
如果两个手势有单项关系,就是一个手势阻止另外一个手势,那么使用:
canPreventGestureRecognizer:或者canBePreventedByGestureRecognizer:

在IOS6之后,许多控件只支持单种手势:
UIButton, UISwitch, UIStepper, UISegmentedControl, and UIPageControl支持单击
A single finger swipe on the knob of a UISlider, in a direction parallel to the slider.
A single finger pan gesture on the knob of a UISwitch, in a direction parallel to the switch.

多点触控和触摸阶段:
[img]http://dl.iteye.com/upload/attachment/0082/7168/63cc99f4-7a5d-379e-89f4-1e5d2bf37e88.png[/img]

触摸传送路径:
[img]http://dl.iteye.com/upload/attachment/0082/7170/b4840760-3279-3fa0-834e-2d0c3a88baf6.png[/img]
如果被touch对象被识别到,那么window不会传送给view了。

UIGestureRecognizer有两个属性:
delaysTouchesBegan(默认是NO):让手势识别到这个动作,如果设置成yes,那么view的响应会比较慢
delaysTouchesEnded(默认是YES):手势可能会取消,留足时间。


//定义头文件
#import <UIKit/UIGestureRecognizerSubclass.h>
//重写UIGestureRecognizer的方法
- (void)reset;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;

//实现部分
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
if ([touches count] != 1) {
self.state = UIGestureRecognizerStateFailed;
return; }
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
UIWindow *win = [self.view window];
CGPoint nowPoint = [touches.anyObject locationInView:win];
CGPoint nowPoint = [touches.anyObject locationInView:self.view];
CGPoint prevPoint = [touches.anyObject previousLocationInView:self.view];
// strokeUp is a property
if (!self.strokeUp) {
} }
// On downstroke, both x and y increase in positive direction
if (nowPoint.x >= prevPoint.x && nowPoint.y >= prevPoint.y) {
self.midPoint = nowPoint;
// Upstroke has increasing x value but decreasing y value
} else if (nowPoint.x >= prevPoint.x && nowPoint.y <= prevPoint.y) {
self.strokeUp = YES;
} else {
self.state = UIGestureRecognizerStateFailed;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
if ((self.state == UIGestureRecognizerStatePossible) && self.strokeUp) {
self.state = UIGestureRecognizerStateRecognized;
}
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
self.midPoint = CGPointZero;
self.strokeUp = NO;
self.state = UIGestureRecognizerStateFailed;
}

//手势重置
- (void)reset {
[super reset];
self.midPoint = CGPointZero;
self.strokeUp = NO;
}


事件传送,Responder chain:
1. The touch is within the bounds of view A, so it checks subviews B and C.
2. The touch is not within the bounds of view B, but it’s within the bounds of view C, so it checks subviews
D and E.
3. The touch is not within the bounds of view D, but it’s within the bounds of view E.
View E is the lowest view in the view hierarchy that contains the touch, so it becomes the hit-test view.
[img]http://dl.iteye.com/upload/attachment/0082/7594/4c50fcd8-b91a-3e89-8e93-2ea00f16b81c.png[/img]

The responder chain是一系列关联的responder对象
得先重写canBecomeFirstResponder方法,返回YES;
responder对象包括:Touch events、Motion events(sharking)、Remote control events、Action messages、Editing-menu messages、Text editing

The responder chain on iOS
[img]http://dl.iteye.com/upload/attachment/0082/7596/d4fd9c9f-fcd0-3c48-8dd5-0c6f0a118b8f.png[/img]
通过方法nextResponder来传递响应

只要是UIResponder的子类都可以处理事件,就像UIView、UIViewController、UIControl、UIApplication or UIWindow,处理类需要实现touch对应的方法,并且设置userInteractionEnabled为YES,而且处理的view等不能为空或者隐藏

多点触碰:
[img]http://dl.iteye.com/upload/attachment/0082/7598/06503c55-5bab-3b17-8818-ea49b2230816.png[/img]
触摸对象的检索和查询:
multipleTouchEnabled属性默认为NO,表示只能响应第一个触碰事件。通过locationInView:获取位置信息,通过allTouches方法获取所有的touch,指定一个Window,使用touchesForWindow:获取所有的touch,指定一个view,使用touchesForView:获取所有的touch
[img]http://dl.iteye.com/upload/attachment/0082/7604/f3f032ca-af67-3c40-8ff1-dad4181a496d.png[/img]
[img]http://dl.iteye.com/upload/attachment/0082/7606/fd827142-a396-37cf-bc6f-99c9d4533b72.png[/img]
[img]http://dl.iteye.com/upload/attachment/0082/7608/e2480999-51b6-3dee-96ac-d943d9461d06.png[/img]


//检测一个双击动作
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *aTouch in touches) {
if (aTouch.tapCount >= 2) {
// The view responds to the tap
[self respondToDoubleTapGesture:aTouch];
} }
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}

//Tracking a swipe gesture in a view
#define HORIZ_SWIPE_DRAG_MIN 12
#define VERT_SWIPE_DRAG_MAX 4
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
// startTouchPosition is a property
self.startTouchPosition = [aTouch locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGPoint currentTouchPosition = [aTouch locationInView:self];
// Check if direction of touch is horizontal and long enough
if (fabsf(self.startTouchPosition.x - currentTouchPosition.x) >=
HORIZ_SWIPE_DRAG_MIN &&
fabsf(self.startTouchPosition.y - currentTouchPosition.y) <=
VERT_SWIPE_DRAG_MAX)
{
// If touch appears to be a swipe
if (self.startTouchPosition.x < currentTouchPosition.x) {[self myProcessRightSwipe:touches withEvent:event];
} else {
[self myProcessLeftSwipe:touches withEvent:event];
}
self.startTouchPosition = CGPointZero;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
self.startTouchPosition = CGPointZero;
}

//Dragging a view using a single touch
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *aTouch = [touches anyObject];
CGPoint loc = [aTouch locationInView:self];
CGPoint prevloc = [aTouch previousLocationInView:self];
CGRect myFrame = self.frame;
float deltaX = loc.x - prevloc.x;
float deltaY = loc.y - prevloc.y;
myFrame.origin.x += deltaX;
myFrame.origin.y += deltaY;
[self setFrame:myFrame];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}

//Storing the beginning locations of multiple touches
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self cacheBeginPointForTouches:touches];
}
- (void)cacheBeginPointForTouches:(NSSet *)touches {
if ([touches count] > 0) {
for (UITouch *touch in touches) {
CGPoint *point = (CGPoint *)CFDictionaryGetValue(touchBeginPoints,
touch);
} }
if (point == NULL) {
point = (CGPoint *)malloc(sizeof(CGPoint));
CFDictionarySetValue(touchBeginPoints, touch, point);
}
*point = [touch locationInView:view.superview];
}

//Retrieving the initial locations of touch objects
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { CGAffineTransform newTransform = [self incrementalTransformWithTouches:touches];
}
- (CGAffineTransform)incrementalTransformWithTouches:(NSSet *)touches {
NSArray *sortedTouches = [[touches allObjects]
sortedArrayUsingSelector:@selector(compareAddress:)];
// Other code here
CGAffineTransform transform = CGAffineTransformIdentity;UITouch *touch1 = [sortedTouches objectAtIndex:0];
UITouch *touch2 = [sortedTouches objectAtIndex:1];
CGPoint beginPoint1 = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints,
touch1);
CGPoint currentPoint1 = [touch1 locationInView:view.superview];
CGPoint beginPoint2 = *(CGPoint *)CFDictionaryGetValue(touchBeginPoints,
touch2);
CGPoint currentPoint2 = [touch2 locationInView:view.superview];
// Compute the affine transform
return transform;
}

//Handling a complex multitouch sequence
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// App supports only single touches, so anyObject retrieves just
// that touch from touches
UITouch *touch = [touches anyObject];
// Move the placard view only if the touch was in the placard view
if ([touch view] != placardView) {
// In case of a double tap outside the placard view, update
// the placard's display string
if ([touch tapCount] == 2) {
[placardView setupNextDisplayString];
}
return;
}
// Animate the first touch
CGPoint touchPoint = [touch locationInView:self];
[self animateFirstTouchAtPoint:touchPoint];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// If the touch was in the placardView, move the placardView to its location
if ([touch view] == placardView) {
CGPoint location = [touch locationInView:self];
placardView.center = location;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// If the touch was in the placardView, bounce it back to the center
if ([touch view] == placardView) {
} }
// Disable user interaction so subsequent touches
// don't interfere with animation
self.userInteractionEnabled = NO;
[self animatePlacardViewToCenter];
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
// To impose as little impact on the device as possible, simply set
// the placard view's center and transformation to the original values
placardView.center = self.center;
placardView.transform = CGAffineTransformIdentity;
}

//Determining when the last touch in a multitouch sequence has ended
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
if ([touches count] == [[event touchesForView:self] count]) {
// Last finger has lifted
}
}

要处理复杂的手势事件,需要把属性multipleTouchEnabled设置为YES,设置属性exclusiveTouch(默认是NO),不会阻止其他view接受触摸,设置为YES就会阻止其他view接受触碰

B和C都不能接受touch
[img]http://dl.iteye.com/upload/attachment/0082/7612/c995dafb-f817-3802-9852-979cbec6f756.png[/img]

把userInteractionEnabled设置成NO就关闭了事件的响应链。不过也可以通过beginIgnoringInteractionEvents和endIgnoringInteractionEvents来间断的阻止响应链(一般动画的时候,不需要触碰)

如果要拦截touch,可以重写方法hitTest:withEvent:,不需要实现 touchesBegan:withEvent:, touchesEnded:withEvent:, or touchesMoved:withEvent:

转发touch事件

//转发touch事件
- (void)sendEvent:(UIEvent *)event {
for (TransformGesture *gesture in transformGestures) {
// Collect all the touches you care about from the event
NSSet *touches = [gesture observedTouchesForEvent:event];
NSMutableSet *began = nil;
NSMutableSet *moved = nil;
NSMutableSet *ended = nil;
NSMutableSet *canceled = nil;
// Sort touches by phase to handle—-similar to normal event dispatch
for (UITouch *touch in touches) {
switch ([touch phase]) {
case UITouchPhaseBegan:
if (!began) began = [NSMutableSet set];
[began addObject:touch];
break;
case UITouchPhaseMoved:
if (!moved) moved = [NSMutableSet set];
[moved addObject:touch];
break;
case UITouchPhaseEnded:
if (!ended) ended = [NSMutableSet set];
[ended addObject:touch];
break;
case UITouchPhaseCancelled:
if (!canceled) canceled = [NSMutableSet set];
[canceled addObject:touch];
break;
default:
break;
// Call methods to handle the touches
if (began)
if (moved)
if (ended)
if (canceled) [gesture touchesCancelled:canceled withEvent:event];
[gesture touchesBegan:began withEvent:event];
[gesture touchesMoved:moved withEvent:event];
[gesture touchesEnded:ended withEvent:event];
}
[super sendEvent:event];
}


Best Practices for Handling Multitouch Events
非常实用

屏幕方向改变识别

//Responding to changes in device orientation
-(void) viewDidLoad {
// Request to turn on accelerometer and begin receiving accelerometer events
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)orientationChanged:(NSNotification *)notification {
// Respond to changes in device orientation
}
-(void) viewDidDisappear {
// Request to stop receiving accelerometer events and turn off accelerometer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
}


Motion Events

//Becoming first responder
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)viewDidAppear:(BOOL)animated {
[self becomeFirstResponder];
}
//Handling a motion event
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (motion == UIEventSubtypeMotionShake)
{
// User was shaking the device. Post a notification named "shake."
[[NSNotificationCenter defaultCenter] postNotificationName:@"shake"
object:self];
} }


如果应用程序想要使用陀螺仪或者加速器等硬件,那么需要在plist文件中定义
key:UIRequiredDeviceCapabilities value:accelerometer、gyroscope

获取设备的移动:Motion events是通过三个类来呈现移动的
CMAccelerometerData:
CMGyroData:
CMDeviceMotion:

CMMotionManager是核心的管理类,它提供两种方式来获取数据,推、拉(推荐)

Common update intervals for acceleration events
[img]http://dl.iteye.com/upload/attachment/0082/8794/b0cdb14f-0251-30ec-a1a5-1c2d98019fdf.png[/img]

Accessing accelerometer data in MotionGraphs

static const NSTimeInterval accelerometerMin = 0.01;
- (void)startUpdatesWithSliderValue:(int)sliderValue {
// Determine the update interval
NSTimeInterval delta = 0.005;
NSTimeInterval updateInterval = accelerometerMin + delta * sliderValue;
// Create a CMMotionManager
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication
sharedApplication] delegate] sharedManager];
APLAccelerometerGraphViewController * __weak weakSelf = self;
// Check whether the accelerometer is available
if ([mManager isAccelerometerAvailable] == YES) {
// Assign the update interval to the motion manager
[mManager setAccelerometerUpdateInterval:updateInterval];
[mManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
[weakSelf.graphView addX:accelerometerData.acceleration.x
y:accelerometerData.acceleration.y z:accelerometerData.acceleration.z];
[weakSelf setLabelValueX:accelerometerData.acceleration.x
y:accelerometerData.acceleration.y z:accelerometerData.acceleration.z];
}]; }
self.updateIntervalLabel.text = [NSString stringWithFormat:@"%f",
updateInterval];
}
- (void)stopUpdates {
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication
sharedApplication] delegate] sharedManager];
if ([mManager isAccelerometerActive] == YES) {
[mManager stopAccelerometerUpdates];
} }


Accessing gyroscope data in MotionGraphs

static const NSTimeInterval gyroMin = 0.01;
- (void)startUpdatesWithSliderValue:(int)sliderValue {// Determine the update interval
NSTimeInterval delta = 0.005;
NSTimeInterval updateInterval = gyroMin + delta * sliderValue;
// Create a CMMotionManager
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication
sharedApplication] delegate] sharedManager];
APLGyroGraphViewController * __weak weakSelf = self;
// Check whether the gyroscope is available
if ([mManager isGyroAvailable] == YES) {
// Assign the update interval to the motion manager
[mManager setGyroUpdateInterval:updateInterval];
[mManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMGyroData *gyroData, NSError *error) {
[weakSelf.graphView addX:gyroData.rotationRate.x
y:gyroData.rotationRate.y z:gyroData.rotationRate.z];
[weakSelf setLabelValueX:gyroData.rotationRate.x
y:gyroData.rotationRate.y z:gyroData.rotationRate.z];
}]; }
self.updateIntervalLabel.text = [NSString stringWithFormat:@"%f",
updateInterval];
}
- (void)stopUpdates{
CMMotionManager *mManager = [(APLAppDelegate *)[[UIApplication
sharedApplication] delegate] sharedManager];
if ([mManager isGyroActive] == YES) {
[mManager stopGyroUpdates];
} }


Starting and stopping device motion updates

- (void)startDeviceMotion {
// Create a CMMotionManager
motionManager = [[CMMotionManager alloc] init];
// Tell CoreMotion to show the compass calibration HUD when required
// to provide true north-referenced attitude
motionManager.showsDeviceMovementDisplay = YES;
motionManager.deviceMotionUpdateInterval = 1.0 / 60.0;
// Attitude that is referenced to true north
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical];
}
- (void)stopDeviceMotion {
[motionManager stopDeviceMotionUpdates];
}


远程控制

//Preparing to receive remote control events
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Turn on remote control event delivery
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
// Set itself as the first responder
[self becomeFirstResponder];
}


//Ending the receipt of remote control events
- (void)viewWillDisappear:(BOOL)animated {
// Turn off remote control event delivery
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
// Resign as first responder
[self resignFirstResponder];
[super viewWillDisappear:animated];
}

//Handling remote control events
- (void)remoteControlReceivedWithEvent:(UIEvent *)receivedEvent {
if (receivedEvent.type == UIEventTypeRemoteControl) {
switch (receivedEvent.subtype) {
} }
}
case UIEventSubtypeRemoteControlTogglePlayPause:
[self playOrStop: nil];
break;
case UIEventSubtypeRemoteControlPreviousTrack:
[self previousTrack: nil];
break;
case UIEventSubtypeRemoteControlNextTrack:
[self nextTrack: nil];
break;
default:
break;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值