If your gesture involves a specific pattern of events, consider implementing a discrete gesture recognizer for it.
A gesture recognizer remains in the
UIGesture state until events indicate that your gesture succeeded or failed, at which point you change its state. The advantage of discrete gesture recognizers is that they are simpler to implement because they require fewer state transitions. One disadvantage is that because the state change typically occurs later in the event sequence, recognition can easily be preempted by continuous gestures attached to the same view.
Figure 1 shows a checkmark gesture, which is created by tracing one finger down and to the right and then back up and to the right. Because the gesture follows a specific path, it makes sense to use a discrete gesture recognizer.
Defining the Conditions for Success
Before implementing your gesture recognizer code, define the conditions for which recognition should occur. The conditions for matching a checkmark gesture are as follows:
Only the first finger to touch the screen is tracked. All others are ignored.
The touch always moves left to right.
The touch moves downward initially but then changes direction and moves upward.
The upward stroke ends higher on the screen than the initial touch point.
Saving Gesture-Related Data
With the conditions defined, add properties to your gesture recognizer to track any needed information. For the checkmark gesture, the gesture recognizer needs to know the starting point of the gesture so that it can compare that point to the final point. It also needs to know whether the user’s finger is moving downward or upward.
Listing 1 shows the first part of a custom
Checkmark class definition. This class stores the initial touch point and the current phase of the gesture. The class also stores the
UITouch object associated with the first finger so that it can ignore any other touches.
Processing Touch Events
Listing 2 shows the
touches method, which sets up the initial conditions for recognizing the gesture. The gesture fails immediately if the initial event contains two touches. If there is only one touch, the touch object is saved in the
tracked property. Because UIKit reuses
UITouch objects, and therefore overwrites their properties, this method also saves the location of the touch in the
initial property. After the first touch occurs, any new touches added to the event sequence are ignored.
When touch information changes, UIKit calls the
touches method. Listing 3 shows the implementation of this method for the checkmark gesture. This method verifies that the first touch is the correct one, which it should be because all subsequent touches were ignored. It then looks at the movement of that touch. When the initial movement is down and to the right, this method sets the
stroke property to
down. When the motion changes direction and starts moving upward, the method changes the stroke phase to
up. If the gesture deviates from this pattern in any way, the method sets the gesture’s state to failed.
At the end of the touch sequence, UIKit calls the
touches method. Listing 4 shows the implementation of this method for the checkmark gesture. If the gesture has not already failed, this method determines whether the gesture was moving upward when it ended and determines whether the final point is higher than the initial point. If both conditions are true, the method sets the state to
recognized; otherwise, the gesture fails.