theflarenet theflarenet - 7 months ago 157
Swift Question

Swift - UISwipeGestureRecognizer Within UIScrollView

I believe I found a solution but it's in Obj-C and I'm completely new & confused into interpreting this into Swift: Horizontal UISwipeGestureRecognizer in subview of UIScrollView ? (UIScrollView only needs to recognize vertical scrolling)

I have my Main.storyboard which adds two sub-views where I can scroll horizontally between them. Currently, up and down swipes are detected but not the left and right due to the UIScrollView. Any workaround this interference?

Main.storyboard:

// Global
let vc0 = ViewController0(nibName: "ViewController0", bundle: nil)
let vc1 = ViewController1(nibName: "ViewController1", bundle: nil)

class ViewController: UIViewController, UIScrollViewDelegate, UIGestureRecognizerDelegate {

@IBOutlet weak var scrollView: UIScrollView!

override func viewDidLoad() {
super.viewDidLoad()

self.addChildViewController(vc0)
self.scrollView.addSubview(vc0.view)
vc0.didMoveToParentViewController(self)

var frame1 = vc1.view.frame
frame1.origin.x = self.view.frame.size.width
vc1.view.frame = frame1

self.addChildViewController(vc1)
self.scrollView.addSubview(vc1.view)
vc1.didMoveToParentViewController(self)

self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height - 66)
self.scrollView.delegate = self

// Swipe Gesture Recognizers
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeUp.direction = UISwipeGestureRecognizerDirection.Up
let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
swipeDown.direction = UISwipeGestureRecognizerDirection.Down

swipeRight.delegate = self
swipeLeft.delegate = self

self.view.addGestureRecognizer(swipeRight)
self.view.addGestureRecognizer(swipeLeft)
self.view.addGestureRecognizer(swipeUp)
self.view.addGestureRecognizer(swipeDown)
}

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}

func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}

// Debugging - Only Up & Down Swipes Are Detected
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
}
}
}
}

Answer

I think you need to implement the UIGestureRecognizerDelegate protocol

Does this achieve what you're looking for?

import UIKit

class ViewController: UIViewController, UIScrollViewDelegate, UIGestureRecognizerDelegate {

    @IBOutlet weak var scrollView: UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // these were made in a storyboard I whipped up for this example.
        let vc0 = self.storyboard!.instantiateViewControllerWithIdentifier("vc0")
        let vc1 = self.storyboard!.instantiateViewControllerWithIdentifier("vc1")

        self.addChildViewController(vc0)
        self.scrollView.addSubview(vc0.view)
        vc0.didMoveToParentViewController(self)

        var frame1 = vc1.view.frame
        frame1.origin.x = self.view.frame.size.width
        vc1.view.frame = frame1

        self.addChildViewController(vc1)
        self.scrollView.addSubview(vc1.view)
        vc1.didMoveToParentViewController(self)

        self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height - 66)
        self.scrollView.delegate = self

        // Swipe Gesture Recognizers
        // These can be lets because they aren't mutated and I'm using the latest Selector syntax
        let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
        swipeRight.direction = UISwipeGestureRecognizerDirection.Right
        let swipeLeft = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
        swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
        let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
        swipeUp.direction = UISwipeGestureRecognizerDirection.Up
        let swipeDown = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.respondToSwipeGesture(_:)))
        swipeDown.direction = UISwipeGestureRecognizerDirection.Down

        // ViewController will be the delegate for the left and right swipes
        swipeRight.delegate = self
        swipeLeft.delegate = self

        self.view.addGestureRecognizer(swipeRight)
        self.view.addGestureRecognizer(swipeLeft)
        self.view.addGestureRecognizer(swipeUp)
        self.view.addGestureRecognizer(swipeDown)
    }

    // here are those protocol methods with Swift syntax
    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        return true
    }

    // Debugging - All Swipes Are Detected Now
    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
            }
        }
    }
}