diff --git a/Resources/DRViewController.xib b/Resources/DRViewController.xib index fea9251..96567da 100644 --- a/Resources/DRViewController.xib +++ b/Resources/DRViewController.xib @@ -1,22 +1,22 @@ - 1296 - 11D50b - 2182 - 1138.32 - 568.00 + 1536 + 12C3012 + 2844 + 1187.34 + 625.00 com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 1181 + 1930 - IBUILabel + IBProxyObject IBUIButton IBUIImageView - IBUIView + IBUILabel IBUISwitch - IBProxyObject + IBUIView com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -103,7 +103,7 @@ {{209, 73}, {28, 28}} - + _NS:225 NO IBCocoaTouchFramework @@ -161,7 +161,7 @@ - {{33, 95}, {270, 138}} + {{33, 130}, {270, 138}} @@ -175,7 +175,7 @@ {{200, 20}, {94, 27}} - + _NS:9 NO IBCocoaTouchFramework @@ -200,15 +200,16 @@ 1 MCAwIDAAA + darkTextColor 0 10 - + 1 17 - + Helvetica 17 16 @@ -217,10 +218,10 @@ 292 - {{22, 55}, {292, 40}} + {{0, 55}, {320, 40}} - + _NS:9 NO YES @@ -233,16 +234,65 @@ 0 10 1 - + 1 25 - + Helvetica 25 16 + + + 292 + {{0, 89}, {320, 40}} + + + + _NS:9 + NO + YES + 7 + NO + IBCocoaTouchFramework + ↑↑↓↓←→←→BA + + 3 + MC4zMzMzMzMzMzMzAA + + + 0 + 10 + 1 + + + + + + 293 + {{0, 342}, {320, 118}} + + + + _NS:9 + NO + YES + 7 + NO + IBCocoaTouchFramework + Test it out! Start with a swipe up. You will see arrow characters that indicate your progress + + + 0 + 0 + 1 + + + NO + 320 + {{0, 20}, {320, 460}} @@ -250,10 +300,7 @@ 3 - MC43NQA - - 2 - + MC45MgA NO @@ -359,6 +406,8 @@ + + @@ -414,6 +463,16 @@ + + 27 + + + + + 29 + + + @@ -428,6 +487,8 @@ com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin com.apple.InterfaceBuilder.IBCocoaTouchPlugin @@ -436,7 +497,7 @@ - 26 + 29 @@ -497,7 +558,7 @@ IBCocoaTouchFramework com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - + YES 3 @@ -505,6 +566,6 @@ nes.png {270, 138} - 1181 + 1930 diff --git a/Sources/DRKonamiGestureRecognizer.h b/Sources/DRKonamiGestureRecognizer.h index 25df655..5252dea 100644 --- a/Sources/DRKonamiGestureRecognizer.h +++ b/Sources/DRKonamiGestureRecognizer.h @@ -6,12 +6,22 @@ // /** + DRKonamiGestureProtocol is optional! + The Konami Gesture protocol implements communication between the gesture recognizer and the delegate when the A+B+Enter action is required to complete the gesture. If the A+B+Enter sequence is not used then none of the protocol methods are required. */ @class DRKonamiGestureRecognizer; @protocol DRKonamiGestureProtocol @required + +/** + Informs the delegate that the gesture recognizer has reached the point where the B+A+Enter sequence is requied to complete the gesture. This is when your code would add UI on the screen to represent the B+A+Enter options. + */ - (void)DRKonamiGestureRecognizerNeedsABEnterSequence:(DRKonamiGestureRecognizer*)gesture; + +/** + Informs the delegate that the gesture recognizer no longers requires the B+A+Enter sequence. This will happen either because the sequence has succeeded or failed. This is where you can remove the B+A+Enter options from the screen. + */ - (void)DRKonamiGestureRecognizer:(DRKonamiGestureRecognizer*)gesture didFinishNeedingABEnterSequenceWithError:(BOOL)error; @end diff --git a/Sources/DRKonamiGestureRecognizer.m b/Sources/DRKonamiGestureRecognizer.m index 9bdc8d3..65c8f72 100644 --- a/Sources/DRKonamiGestureRecognizer.m +++ b/Sources/DRKonamiGestureRecognizer.m @@ -6,93 +6,28 @@ // #import "DRKonamiGestureRecognizer.h" -#import +#import // required for subclassing UIGestureRecognizer + +/////////////////////////////////////////////////////////////// // Line below disables logging if uncommented #define NSLog(...); -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////// +// Constant Declarations +static const CGFloat kKonamiSwipeDistanceTolerance = 50.0f; // Max tolerence in direction perpendicular to expected swipe state +static const CGFloat kKonamiSwipeDistanceMin = 50.0f; // Min distance to detect a swipe gesture +static const NSTimeInterval kKonamiGestureMaxTimeBetweenGestures = 1.0f; // The max time allowed between swipe gestures. +static const NSTimeInterval kKonamiGestureMaxTimeDuringGesture = 1.0f; // The max time allowed during swipe gestures. -void getCheckValuesAfterTouchesEnded(DRKonamiGestureState konamiState, BOOL* pCheckXLeft, BOOL* pCheckXRight, BOOL* pCheckYUp, BOOL* pCheckYDown); -void getCheckValuesDuringDrag(DRKonamiGestureState konamiState, BOOL* pCheckX, BOOL* pCheckY); +/////////////////////////////////////////////////////////////// -void getCheckValuesAfterTouchesEnded(DRKonamiGestureState konamiState, BOOL* pCheckXLeft, BOOL* pCheckXRight, BOOL* pCheckYUp, BOOL* pCheckYDown) -{ - switch (konamiState) - { - case DRKonamiGestureStateBegan: - case DRKonamiGestureStateUp1: - case DRKonamiGestureStateUp2: - *pCheckYUp = YES; - break; - case DRKonamiGestureStateDown1: - case DRKonamiGestureStateDown2: - *pCheckYDown = YES; - break; - - case DRKonamiGestureStateLeft1: - case DRKonamiGestureStateLeft2: - *pCheckXLeft = YES; - break; - - case DRKonamiGestureStateRight1: - case DRKonamiGestureStateRight2: - *pCheckXRight = YES; - break; - - case DRKonamiGestureStateB: - case DRKonamiGestureStateA: - break; - - case DRKonamiGestureStateRecognized: - case DRKonamiGestureStateNone: - default: - NSLog(@"unexpected gesture state %d (in %s)", konamiState, __FUNCTION__); - break; - - } -} +// Some helper functions +void getCheckValuesAfterTouchesEnded(DRKonamiGestureState konamiState, BOOL* pCheckXLeft, BOOL* pCheckXRight, BOOL* pCheckYUp, BOOL* pCheckYDown); -void getCheckValuesDuringDrag(DRKonamiGestureState konamiState, BOOL* pCheckX, BOOL* pCheckY) -{ - switch (konamiState) - { - case DRKonamiGestureStateBegan: - case DRKonamiGestureStateUp1: - case DRKonamiGestureStateUp2: - case DRKonamiGestureStateDown1: - case DRKonamiGestureStateDown2: - *pCheckX = YES; - break; - - case DRKonamiGestureStateLeft1: - case DRKonamiGestureStateRight1: - case DRKonamiGestureStateLeft2: - case DRKonamiGestureStateRight2: - *pCheckY = YES; - break; - - case DRKonamiGestureStateB: - case DRKonamiGestureStateA: - break; - - case DRKonamiGestureStateRecognized: - case DRKonamiGestureStateNone: - default: - NSLog(@"unexpected gesture state %d (in %s)", konamiState, __FUNCTION__); - break; - - } -} +void getCheckValuesDuringDrag(DRKonamiGestureState konamiState, BOOL* pCheckX, BOOL* pCheckY); -//////////////////////////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////////////////////////// -static const CGFloat kKonamiSwipeDistanceTolerance = 50.0f; // Max tolerence in direction perpendicular to expected swipe state -static const CGFloat kKonamiSwipeDistanceMin = 50.0f; // Min distance to detect a swipe gesture -static const NSTimeInterval kKonamiGestureMaxTimeBetweenGestures = 1.0f; // The max time allowed between swipe gestures. -static const NSTimeInterval kKonamiGestureMaxTimeDuringGesture = 1.0f; // The max time allowed during swipe gestures. +/////////////////////////////////////////////////////////////// @interface DRKonamiGestureRecognizer () @property (nonatomic, assign, readwrite) DRKonamiGestureState konamiState; @@ -100,6 +35,8 @@ @interface DRKonamiGestureRecognizer () @property (nonatomic, assign, readwrite) CGPoint lastGestureStartPoint; @end +/////////////////////////////////////////////////////////////// + @implementation DRKonamiGestureRecognizer @synthesize konamiState = _konamiState; @synthesize lastGestureDate = _lastGestureDate; @@ -127,12 +64,13 @@ - (id) initWithTarget:(id)target action:(SEL)action - (id) init { + NSLog(@"Invalid initalizer: %s", __FUNCTION__); return nil; } - (void) dealloc { - [_lastGestureDate release]; + self.lastGestureDate = nil; [super dealloc]; } @@ -146,6 +84,8 @@ - (void)reset - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer { + // basically we don't prevent any other recognizer from being recoginzed. + // TODO: Explore the idea of returning YES if self.konamiState != DRKonamiGestureStateNone. return NO; } @@ -184,13 +124,16 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event [self setState:UIGestureRecognizerStateFailed]; return; } - self.lastGestureDate = [NSDate new]; + self.lastGestureDate = [[NSDate new] autorelease]; // autorelease because it's retained twice (new & in setter) UITouch *touch = [touches anyObject]; UIView *view = [self view]; self.lastGestureStartPoint = [touch locationInView:view]; } } +/** + Determine whether the gesture is still happening during a swipe event. + */ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if ( self.konamiState >= DRKonamiGestureStateRight2 ) @@ -209,9 +152,12 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event // Check if user has dragged finger too far away from the gesture axis BOOL checkY = NO; - BOOL checkX = NO; + BOOL checkX = NO; getCheckValuesDuringDrag(self.konamiState + 1, &checkX, &checkY); - // @todo add timeout on swipe gestures + + // TODO add timeout on swipe gestures + + // Check if the X and/or Y distance of the swipe was so far that the gesture if considered failed if (( checkX == YES) || (checkY == YES)) { // Only 1 touch object is possible. @@ -246,6 +192,9 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event } } +/** + At the end of each swipe event determine if the gesture failed or not. + */ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if ( self.konamiState >= DRKonamiGestureStateRight2 ) @@ -317,7 +266,7 @@ - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event } self.konamiState++; - self.lastGestureDate = [NSDate new]; + self.lastGestureDate = [[NSDate new] autorelease]; // autorelease because it's retained twice (new & by setter) [self setState:UIGestureRecognizerStateChanged]; @@ -407,3 +356,81 @@ - (void) cancelSequence } @end + +#pragma mark - +#pragma mark C Helper Functiona + +/** + Determines whether the gesture recognizer needs to check the X and Y touch coordinates depending on the gesture state. + */ +void getCheckValuesAfterTouchesEnded(DRKonamiGestureState konamiState, BOOL* pCheckXLeft, BOOL* pCheckXRight, BOOL* pCheckYUp, BOOL* pCheckYDown) +{ + switch (konamiState) + { + case DRKonamiGestureStateBegan: + case DRKonamiGestureStateUp1: + case DRKonamiGestureStateUp2: + *pCheckYUp = YES; + break; + case DRKonamiGestureStateDown1: + case DRKonamiGestureStateDown2: + *pCheckYDown = YES; + break; + + case DRKonamiGestureStateLeft1: + case DRKonamiGestureStateLeft2: + *pCheckXLeft = YES; + break; + + case DRKonamiGestureStateRight1: + case DRKonamiGestureStateRight2: + *pCheckXRight = YES; + break; + + case DRKonamiGestureStateB: + case DRKonamiGestureStateA: + break; + + case DRKonamiGestureStateRecognized: + case DRKonamiGestureStateNone: + default: + NSLog(@"unexpected gesture state %d (in %s)", konamiState, __FUNCTION__); + break; + + } +} + +/** + Determines whether the gesture recognizer needs to check the X and Y touch coordinates depending on the gesture state. + */ +void getCheckValuesDuringDrag(DRKonamiGestureState konamiState, BOOL* pCheckX, BOOL* pCheckY) +{ + switch (konamiState) + { + case DRKonamiGestureStateBegan: + case DRKonamiGestureStateUp1: + case DRKonamiGestureStateUp2: + case DRKonamiGestureStateDown1: + case DRKonamiGestureStateDown2: + *pCheckX = YES; + break; + + case DRKonamiGestureStateLeft1: + case DRKonamiGestureStateRight1: + case DRKonamiGestureStateLeft2: + case DRKonamiGestureStateRight2: + *pCheckY = YES; + break; + + case DRKonamiGestureStateB: + case DRKonamiGestureStateA: + break; + + case DRKonamiGestureStateRecognized: + case DRKonamiGestureStateNone: + default: + NSLog(@"unexpected gesture state %d (in %s)", konamiState, __FUNCTION__); + break; + } +} +