I want to implement the ability to navigate back and fourth in my webView by using the Event swipeWithEvent. However, I have no idea how I am suppose to use this.
I
From the 10.7 release notes:
Fluid Swipe Tracking - API
The following API allows for tracking gesture scroll wheel events as a fluid swipe gesture. Similar to iOS, NSScrollView will bounce once if needed, then optionally pass on the gesture scroll wheel events so your controller can use this API to track the scroll gesture as a fluid swipe gesture.
ScrollWheel NSEvents now respond to the -phase message. There are 3 types of scrolls:
1) Gesture scrolls - these begin with NSEventPhaseBegan, have a number of NSEventPhaseChanged events and terminate when the user lifts their fingers with an NSEventPhaseEnded.
2) Momentum scrolls - these have a phase of NSEventPhase none, but they have a momentumPhase of NSEventPhaseBegan/NSEventPhaseChanged/NSEventPhaseEnded.
3) Legacy scrolls - these scroll wheel events have a phase of NSEventPhaseNone and a momentumPhase of NSEventPhaseNone. There is no way to determine when the user starts, nor stops, performing legacy scrolls.
NSScrollView processes all gesture scroll wheel events and does not pass them up the responder chain. Often, tracking a swipe is done higher in the responder chain, for example at the WindowController level. To achieve an iOS style "bounce when not at the edge, otherwise swipe" behavior, you need to inform NSScrollView that it should forward scroll wheel messages when appropriate. Instead of manually setting a property on NSScrollView, your NSResponder can implement the following method and return YES.
- (BOOL)wantsScrollEventsForSwipeTrackingOnAxis:(NSEventGestureAxis)axis;When the appropriate controller receives a -scrollWheel: message with a non NSEventNone phase, you can call the following message on that event instance to track the swipe or scroll to both user completion of the event, and animation completion.
enum { NSEventSwipeTrackingLockDirection = 0x1 << 0, NSEventSwipeTrackingClampGestureAmount = 0x1 << 1 }; typedef NSUInteger NSEventSwipeTrackingOptions; @interface NSEvent ... - (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options dampenAmountThresholdMin:(CGFloat)minDampenThreshold max:(CGFloat)maxDampenThreshold usingHandler:(void (^)(CGFloat gestureAmount, NSEventPhase phase, > BOOL isComplete, BOOL *stop))handler; ...Below is a pseudo code example of swiping a collection of pictures like the iOS Photo app.
- (BOOL)wantsScrollEventsForSwipeTrackingOnAxis:(NSEventGestureAxis)axis { return (axis == NSEventGestureAxisHorizontal) ? YES : NO; } - (void)scrollWheel:(NSEvent *)event { // NSScrollView is instructed to only forward horizontal scroll gesture events (see code above). However, depending // on where your controller is in the responder chain, it may receive other scrollWheel events that we don't want // to track as a fluid swipe because the event wasn't routed though an NSScrollView first. if ([event phase] == NSEventPhaseNone) return; // Not a gesture scroll event. if (fabsf([event scrollingDeltaX]) <= fabsf([event scrollingDeltaY])) return; // Not horizontal // If the user has disabled tracking scrolls as fluid swipes in system preferences, we should respect that. // NSScrollView will do this check for us, however, depending on where your controller is in the responder chain, // it may scrollWheel events that are not filtered by an NSScrollView. if (![NSEvent isSwipeTrackingFromScrollEventsEnabled]) return; if (_swipeAnimationCanceled && *_swipeAnimationCanceled == NO) { // A swipe animation is still in gestureAmount. Just kill it. *_swipeAnimationCanceled = YES; _swipeAnimationCanceled = NULL; } CGFloat numPhotosToLeft = // calc num of photos we can move to the left and negate CGFloat numPhotosToRight = // calc num of photos we can move to the right __block BOOL animationCancelled = NO; [event trackSwipeEventWithOptions:0 dampenAmountThresholdMin:numPhotosToLeft max:numPhotosToRight usingHandler:^(CGFloat gestureAmount, NSEventPhase phase, BOOL isComplete, BOOL *stop) { if (animationCancelled) { *stop = YES; // Tear down animation overlay return; } if (phase == NSEventPhaseBegan) { // Setup animation overlay layers } // Update animation overlay to match gestureAmount if (phase == NSEventPhaseEnded) { // The user has completed the gesture successfully. // This handler will continue to get called with updated gestureAmount // to animate to completion, but just in case we need // to cancel the animation (due to user swiping again) setup the // controller / view to point to the new content / index / whatever } else if (phase == NSEventPhaseCancelled) { // The user has completed the gesture un-successfully. // This handler will continue to get called with updated gestureAmount // But we don't need to change the underlying controller / view settings. } if (isComplete) { // Animation has completed and gestureAmount is either -1, 0, or 1. // This handler block will be released upon return from this iteration. // Note: we already updated our view to use the new (or same) content // above. So no need to do that here. Just... // Tear down animation overlay here self->_swipeAnimationCanceled = NULL; } }]; // We keep a pointer to a BOOL __block variable so that we can cancel our // block handler at any time. Note: You must assign the BOOL pointer to your // ivar after block creation and copy! self->_swipeAnimationCanceled = &animationCancelled; }
Other solution would be to directly handle touch event directly in order to recognize gestures. For more information consider to take a look at documentation.