How to recognize swipe in all 4 directions

129,487

Solution 1

You need to have one UISwipeGestureRecognizer for each direction. It's a little weird because the UISwipeGestureRecognizer.direction property is an options-style bit mask, but each recognizer can only handle one direction. You can send them all to the same handler if you want, and sort it out there, or send them to different handlers. Here's one implementation:

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
    swipeRight.direction = .right
    self.view.addGestureRecognizer(swipeRight)

    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
    swipeDown.direction = .down
    self.view.addGestureRecognizer(swipeDown)
}

@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {

    if let swipeGesture = gesture as? UISwipeGestureRecognizer {

        switch swipeGesture.direction {
        case .right:
            print("Swiped right")
        case .down:
            print("Swiped down")
        case .left:
            print("Swiped left")
        case .up:
            print("Swiped up")
        default:
            break
        }
    }
}

Swift 3:

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
    swipeRight.direction = UISwipeGestureRecognizerDirection.right
    self.view.addGestureRecognizer(swipeRight)

    let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
    swipeDown.direction = UISwipeGestureRecognizerDirection.down
    self.view.addGestureRecognizer(swipeDown)
}

func respondToSwipeGesture(gesture: UIGestureRecognizer) {
    if let swipeGesture = gesture as? UISwipeGestureRecognizer {
        switch swipeGesture.direction {
        case UISwipeGestureRecognizerDirection.right:
            print("Swiped right")
        case UISwipeGestureRecognizerDirection.down:
            print("Swiped down")
        case UISwipeGestureRecognizerDirection.left:
            print("Swiped left")
        case UISwipeGestureRecognizerDirection.up:
            print("Swiped up")
        default:
            break
        }
    }
}

Solution 2

I just felt like contributing this, looks more elegant in the end:

func addSwipe() {
    let directions: [UISwipeGestureRecognizerDirection] = [.Right, .Left, .Up, .Down]
    for direction in directions {
        let gesture = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipe:"))
        gesture.direction = direction
        self.addGestureRecognizer(gesture)
    }
}

func handleSwipe(sender: UISwipeGestureRecognizer) {
    print(sender.direction)
}

Solution 3

From the storyboard:

  1. Add four swipe gesture recognizers to your view.
  2. Set each one with the target direction from the attribute inspector. You can select right, left, up or down
  3. One by one, select the swipe gesture recognizer, control + drag to your view controller. Insert the name (let us say leftGesture, rightGesture, upGesture and downGesture), change the connection to: Action and type to: UISwipeGestureRecognizer

From your viewController:

@IBAction func rightGesture(sender: UISwipeGestureRecognizer) {
    print("Right")
}
@IBAction func leftGesture(sender: UISwipeGestureRecognizer) {
    print("Left")
}
@IBAction func upGesture(sender: UISwipeGestureRecognizer) {
    print("Up")
}

@IBAction func downGesture(sender: UISwipeGestureRecognizer) {
    print("Down")
}  

Solution 4

Looks like things have changed lately. In XCode 7.2 the following approach works:

override func viewDidLoad() {
    super.viewDidLoad()

    let swipeGesture = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
    swipeGesture.direction = [.Down, .Up]
    self.view.addGestureRecognizer(swipeGesture)
}

func handleSwipe(sender: UISwipeGestureRecognizer) {
    print(sender.direction)
}

Tested in Simulator on iOS 8.4 and 9.2 and on actual device on 9.2.

Or, using mlcollard's handy extension here:

let swipeGesture = UISwipeGestureRecognizer() {
    print("Gesture recognized !")
}

swipeGesture.direction = [.Down, .Up]
self.view.addGestureRecognizer(swipeGesture)

Solution 5

Apple Swift version 3.1 - Xcode Version 8.3 (8E162)

The handy way from Alexandre Cassagne's approach

let directions: [UISwipeGestureRecognizerDirection] = [.up, .down, .right, .left]
for direction in directions {
    let gesture = UISwipeGestureRecognizer(target: self, action: #selector(YourClassName.handleSwipe(gesture:)))
    gesture.direction = direction
    self.view?.addGestureRecognizer(gesture)   
}

func handleSwipe(gesture: UISwipeGestureRecognizer) {
    print(gesture.direction)
    switch gesture.direction {
    case UISwipeGestureRecognizerDirection.down:
        print("down swipe")
    case UISwipeGestureRecognizerDirection.up:
        print("up swipe")
    case UISwipeGestureRecognizerDirection.left:
        print("left swipe")
    case UISwipeGestureRecognizerDirection.right:
        print("right swipe")
    default:
        print("other swipe")
    }
}
Share:
129,487
user3739367
Author by

user3739367

Updated on January 29, 2022

Comments

  • user3739367
    user3739367 about 2 years

    I need to use swipe to recognize swipe gesture down and then right. But on swift UISwipeGestureRecognizer has predeterminate Right direction.. And I don't know how make this for use other directions..

  • Sergey Skoblikov
    Sergey Skoblikov almost 9 years
    "each recognizer can only handle one direction" - thats not true. See stackoverflow.com/questions/16184539/…
  • King-Wizard
    King-Wizard almost 9 years
    "each recognizer can only handle one direction" - It is true in Swift and false in Objective-C to be specific.
  • Paul Peelen
    Paul Peelen over 8 years
    You do not have to add UISwipeGestureRecognizerDirection in front of .Down ect. Just using swipeDown.direction = .Down if sufficient enough. Just a tip =)
  • Max
    Max over 8 years
    can we add same gestureRecogniser object to more than one view?I have tried but not worked.
  • Knight0fDragon
    Knight0fDragon over 8 years
    if you do @Sergey Skoblikovs's approach in swift, (by doing swipe.direction = [.Right,.Down,.Up,.Left]), the recognizer will not even get called, perhaps this is an issue with swift, but as of right now does not work.
  • user3099333
    user3099333 over 8 years
    By this answer you don't need to write lots of codes but you use the storyboard and connections between storyboard and your code. In case the developer prefers working in this way, this answer might be easier but if the developer prefers working more in coding, definitely the first answer is the best.
  • user3099333
    user3099333 over 8 years
    I used 4 swipe gestures instead of one and lots of the work load is in the storyboard instead of coding.
  • ahitt6345
    ahitt6345 over 8 years
    self.addGestureRecognizer(gesture) caused an error for me. What fixed it was self.view.addGestureRecognizer(gesture);.
  • Alexandre Cassagne
    Alexandre Cassagne about 8 years
    @ahitt6345 I was using my code in a UIView subclass, but you're absolutely right if you're in a UIViewController!
  • Robert Gummesson
    Robert Gummesson about 8 years
    The selector may be called but the direction on the sender is incorrect. In other words, this approach is fine if you don't need to know the direction of the swipe but not otherwise.
  • Vrezh Gulyan
    Vrezh Gulyan over 7 years
    Rather than creating multiple swipe gesture organizers that which all call the same function swipeGesture.direction = UISwipeGestureRecognizerDirection.right self.view.addGestureRecognizer(swipeGesture) swipeGesture.direction = UISwipeGestureRecognizerDirection.left self.view.addGestureRecognizer(swipeGesture)
  • Johannes Knust
    Johannes Knust about 7 years
    the same problem still in xcode 8.3 - compiled but not working - I got just for left and right this back UISwipeGestureRecognizerDirection(rawValue: 15)
  • Allison
    Allison about 7 years
    With this specific build you need to run defaults write com.apple.dt.xcode IDEPlaygroundDisableSimulatorAlternateFramebuffer -bool YES in Terminal to fix a bug on some hardware. It should be fixed in a new version of Xcode
  • Brent Faust
    Brent Faust almost 7 years
    No longer works. In Swift 3, the context must be supplied to the first value: [UISwipeGestureRecognizerDirection.right, .left, .up, .down]
  • Christopher Smit
    Christopher Smit over 6 years
    Clean, best answer for me.
  • Poul Bak
    Poul Bak over 5 years
    Add some description to your code, please that will make it better.
  • mway
    mway almost 5 years
    i think you need an @objc in front of func respondToSwipeGesture for this to work in Swift 4
  • shashwat
    shashwat over 4 years
    How is this an answer to the OP's question? The problem was to find an elegant way to add multiple directions to the swipe gesture recognizer.
  • leafcutter
    leafcutter about 4 years
    You are correct that you need an individual swipe for each direction but you can have a gesture with more than one direction value e.g. swipe.direction = [.left, .right]. The meaning of this is that the gesture recognizer will be triggered if either of these directions occurs and it will not distinguish between them. The rawValue for the enum of UIGestureRecognizer.Direction is 1-right, 2-left, 4-up, 8-down. Setting swipe.direction = [.left, .right] will give a swipe.direction = 3 when you query the gesture in the selector
  • zionpi
    zionpi over 3 years
    For later searcher ,in Swift 5, @objc is still needed in front of func respondToSwipeGesture method.
  • Chris
    Chris over 2 years
    Code is a lot more helpful when it is accompanied by an explanation. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please edit your question and explain how it answers the specific question being asked. See How to Answer.