iOSios基础知识

UIGestureRecognizerDelegate学习笔记

2017-10-28  本文已影响795人  Sniper_Zheng

原文链接

感谢作者ruwatana, 我只是翻译并学习该文. 如果有错误欢迎指正.

前言

如果想控制自定义的UIGestureRecognizer的识别,或者同时控制其他手势的失败的情况,我想应该会很多.
这个时候用UIGestureRecognizerDelegate会方便很多.
虽然提供了各种各样的方法,但是日语的资料不是很多(原文是日语,本文只是翻译一下),总结了一下哪种情况下会用到哪种方法.

UIGestureRecognizerDelegate

UIGestureRecognizerDelegate是一个为了微调手势的识别的protocal.
它提供了6个协议方法,都是optional的.

public protocol UIGestureRecognizerDelegate : NSObjectProtocol {
    // 控制Gesture的开始
    @available(iOS 3.2, *)
    optional public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool

    // 控制Gesture是否可以同时识别
    @available(iOS 3.2, *)
    optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool

    // 控制自身的Gesture和其他Gesture的失败
    @available(iOS 7.0, *)
    optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool
    @available(iOS 7.0, *)
    optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool

    // 控制Gesture是否接受touch
    @available(iOS 3.2, *)
    optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool

    // 控制Gesture是否接受press
    @available(iOS 9.0, *)
    optional public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive press: UIPress) -> Bool
}

使用方法

使用方法很简单.想要实现协议的对象设置为UIGestureRecognizer的delegate就可以了.

class ViewController: UIViewController {
    var gesture: UIGestureRecognizer?
    override func viewDidLoad() {
        super.viewDidLoad()

        // gesture的初始化

        // 设置delegate
        gesture?.delegate = self
    }
}

extension ViewController: UIGestureRecognizerDelegate {
    // 在这里实现delegate方法
}

delegate方法介绍

在这里将UIGestureRecognizerDelegate分为三类控制方法介绍

识别控制系方法

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if gestureRecognizer === tap0gesture { // 判断该gesture是否是指定的gesture 从而进行控制
        // hogehoge
        return false  // tap0click不会被调用
    }
    return true  // tap0click会被调用
}
Screen Shot 2017-10-26 at 9.57.06 AM.png

orangeView的tag是10010

self.view的tag是10012

代码:

class ViewController: UIViewController {
    
    @objc func tap0click(tap: UITapGestureRecognizer) {
        print("tap 10010 click")
    }
    
    @objc func tap2click(tap: UITapGestureRecognizer) {
        print("tap 10012 click")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 第一个view
        let view0 = CustomView0(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
        self.view.addSubview(view0)
        view0.backgroundColor = UIColor.orange
        view0.tag = 10010
        let tap0 = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap0click(tap:)))
        view0.addGestureRecognizer(tap0)
        tap0.delegate = self
        
        let tap2 = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap2click(tap:)))
        self.view.addGestureRecognizer(tap2)
        self.view.tag = 10012
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

extension ViewController : UIGestureRecognizerDelegate {
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        print("gesture recognizer should receive touch in view : \(String(describing: gestureRecognizer.view?.tag))")
        print("gesture recognizer touch in view \(String(describing: touch.view?.tag))")
        return false
    }
    
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        print("gesture recognizer should begin in view : \(String(describing: gestureRecognizer.view?.tag))")
        return true
    }
}

返回的结果为:

Screen Shot 2017-10-28 at 10.16.14 PM.png

如果shouldReceive回调方法返回值为true

返回的结果为:

Screen Shot 2017-10-28 at 10.17.06 PM.png

同时识别控制系方法

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    if gestureRecognizer === self.gesture { // 判断特定手势
        // hogehoge
    }

    if otherGestureRecognizer is UIPanGestureRecognizer { // 判断其他另一个手势
        // hogehoge
    }

    if otherGestureRecognizer.view is UIScrollView { // 判断其他手势是加在UIScrollView上的情况
        // hogehoge
    }
    return false
}

还是上面的orageView那个例子.如果设置同时识别回调方法的返回值为false:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return false
}

返回结果:

Screen Shot 2017-10-28 at 8.54.07 PM.png

如果设置返回值为true:

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

返回结果:

Screen Shot 2017-10-28 at 8.54.39 PM.png

失败控制系方法

这个方法是两个gesture都识别的情况下, 控制gestureRecognizer的失败, 或者另一个otherGestureRecognizer的失败的时候使用.

shouldRequireFailureOf方法 返回TRUE时 参数gestureRecognizer会失败.
shouldBeRequiredToFailBy方法 返回TRUE时 参数otherGestureRecognizer会失败.

Tips: UIKit中的系统类里使用的gesture是不能设置delegate的.
不是自定义的gesture, 而是UIKit中封装好的手势(比如UITableView或者UIScrollView的panGestureRecognizer 等等..)

如果给UITableView(UIScrollView)设置tableview.panGestureRecognizer.delegate = self;, 会崩溃. 提示信息如下:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UIScrollView's built-in pan gesture recognizer must have its scroll view as its delegate.'

原文点击此处

上一篇下一篇

猜你喜欢

热点阅读