用闭包实现手势的链式监听事件

和tips17中的按钮点击事件类似,手势也可以封装成链式闭包回调.

  1. 使用
    1
    2
    3
    4
    5
    6
    view
    .addTapGesture { tap in
    print(tap)
    }.addPinchGesture { pinch in
    print(pinch)
    }

  1. 实现过程
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    public typealias GestureClosures = (UIGestureRecognizer) -> Void
    private var gestureDictKey: Void?

    extension UIView {
    private enum GestureType: String {
    case tapGesture
    case pinchGesture
    case rotationGesture
    case swipeGesture
    case panGesture
    case longPressGesture
    }

    // MARK: - 属性
    private var gestureDict: [String: GestureClosures]? {
    get {
    return objc_getAssociatedObject(self, &gestureDictKey) as? [String: GestureClosures]
    }
    set {
    objc_setAssociatedObject(self, &gestureDictKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
    }
    }

    // MARK: - API
    /// 点击
    @discardableResult
    public func addTapGesture(_ gesture: @escaping GestureClosures) -> UIView {
    addGesture(gesture: gesture, for: .tapGesture)
    return self
    }
    /// 捏合
    @discardableResult
    public func addPinchGesture(_ gesture: @escaping GestureClosures) -> UIView {
    addGesture(gesture: gesture, for: .pinchGesture)
    return self
    }
    // ...省略相关手势

    // MARK: - 私有方法
    private func addGesture(gesture: @escaping GestureClosures, for gestureType: GestureType) {
    let gestureKey = String(gestureType.rawValue)
    if var gestureDict = self.gestureDict {
    gestureDict.updateValue(gesture, forKey: gestureKey)
    self.gestureDict = gestureDict
    } else {
    self.gestureDict = [gestureKey: gesture]
    }
    isUserInteractionEnabled = true
    switch gestureType {
    case .tapGesture:
    let tap = UITapGestureRecognizer(target: self, action: #selector(tapGestureAction(_:)))
    addGestureRecognizer(tap)
    case .pinchGesture:
    let pinch = UIPinchGestureRecognizer(target: self, action: #selector(pinchGestureAction(_:)))
    addGestureRecognizer(pinch)
    default:
    break
    }
    }
    @objc private func tapGestureAction (_ tap: UITapGestureRecognizer) {
    executeGestureAction(.tapGesture, gesture: tap)
    }
    @objc private func pinchGestureAction (_ pinch: UIPinchGestureRecognizer) {
    executeGestureAction(.pinchGesture, gesture: pinch)
    }

    private func executeGestureAction(_ gestureType: GestureType, gesture: UIGestureRecognizer) {
    let gestureKey = String(gestureType.rawValue)
    if let gestureDict = self.gestureDict, let gestureReg = gestureDict[gestureKey] {
    gestureReg(gesture)
    }
    }
    }