美文网首页Swift工作笔记Swift
Swift.用RunTime和Extension的方式为UIVi

Swift.用RunTime和Extension的方式为UIVi

作者: 王四猫 | 来源:发表于2018-11-01 11:36 被阅读7次
效果图

前言:

我们在开发工作中很有可能遇到需要view相应各种手势的需求,使用RunTime+Extension的形式为UIView进行拓展,代码的复用性,可读性都很高.

实现效果:

为UIView及其子类添加了点击,双击,长按,上滑,左滑,右滑,下滑手势方法,调用方法简单轻便.

实现方式:

1.添加滑动手势协议.

2.设置RunTime添加属性时的Key.

3.创建点击,长按,滑动手势类.

4.使用Extension为UIView进行拓展.


1.添加滑动手势协议.

在协议中添加滑动事件以及相应触发方法.

 ///添加点击事件协议
protocol UIViewTapable {
    ///单击事件
    var tapHandlers: [CRTapGestureHanler] { get }
    ///双击事件
    var doubleTapGestureHandlers: [CRTapGestureHanler]{ get }
    ///长点事件
    var longTapGestureHandlers: [CRTapGestureHanler]{ get }
    ///上滑事件
    var upSwipeGestureHandlers: [CRTapGestureHanler]{ get }
    ///左滑事件
    var leftSwipeGestureHandlers: [CRTapGestureHanler]{ get }
    ///右滑事件
    var rightSwipeGestureHandlers: [CRTapGestureHanler]{ get }
    ///下滑事件
    var downSwipeGestureHandlers: [CRTapGestureHanler]{ get }

    func whenTapped(handler:@escaping()->Void)
    func whenDoubleTapped(handler:@escaping()->Void)
    func whenLongPressed(handler:@escaping()->Void)
    func whenUpSwiped(handler:@escaping()->Void)
    func whenLeftSwiped(handler:@escaping()->Void)
    func whenRightSwiped(handler:@escaping()->Void)
    func whenDownSwiped(handler:@escaping()->Void)

}

2.设置RunTime添加属性时的Key.

在这里我们设置所有手势相应的String标识以及与之对应的内存地址Key.

///runtime绑定方法时的key
class EWGestureAssociatedObjectKey {
    ///设置不同手势不同String标识
    static let EWTapGestureAssociatedObjectString  = "EWTapGestureAssociatedObjectString"
    ///获取String标识的内存地址作为runtime属性的Key
    static var EWTapGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWTapGestureAssociatedObjectString as AnyObject).toOpaque()}()

    static let EWDoubleTapGestureAssociatedObjectString  = "EWDoubleTapGestureAssociatedObjectString"
    static var EWDoubleTapGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWDoubleTapGestureAssociatedObjectString as AnyObject).toOpaque()}()

    static let EWLongTapGestureAssociatedObjectString  = "EWLongTapGestureAssociatedObjectString"
    static var EWLongTapGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWLongTapGestureAssociatedObjectString as AnyObject).toOpaque()}()

    static let EWUpSwipeGestureAssociatedObjectString  = "EWUpSwipeGestureAssociatedObjectString"
    static var EWUpSwipeGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWUpSwipeGestureAssociatedObjectString as AnyObject).toOpaque()}()

    static let EWLeftSwipeGestureAssociatedObjectString  = "EWLeftSwipeGestureAssociatedObjectString"
    static var EWLeftSwipeGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWLeftSwipeGestureAssociatedObjectString as AnyObject).toOpaque()}()

    static let EWRightSwipeGestureAssociatedObjectString  = "EWRightSwipeGestureAssociatedObjectString"
    static var EWRightSwipeGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWRightSwipeGestureAssociatedObjectString as AnyObject).toOpaque()}()

    static let EWDownSwipeGestureAssociatedObjectString  = "EWDownSwipeGestureAssociatedObjectString"
    static var EWDownSwipeGestureKey = {return Unmanaged<AnyObject>.passUnretained(EWGestureAssociatedObjectKey.EWDownSwipeGestureAssociatedObjectString as AnyObject).toOpaque()}()

}

3.创建点击,长按,滑动手势类.

单击双击都是点击手势,使用EWTapGesture,上下左右滑动手势使用EWSwipeGesture

 ///单击双击手势
class EWTapGesture: NSObject, UIGestureRecognizerDelegate{
    fileprivate weak var myView:UIView!
    fileprivate let gesture : UITapGestureRecognizer
    ///手势储存外界闭包
    fileprivate var tappedHandler = [EWTapGestureHanler]()

    init(view: UIView,taps: Int = 1) {
        myView = view
        ///手势
        gesture = UITapGestureRecognizer()
        super.init()
        gesture.delegate = self
        gesture.numberOfTapsRequired = taps
        gesture.addTarget(self, action: #selector(EWTapGesture.tapped(_:)))
        myView.addGestureRecognizer(gesture)
        if taps == 1 {
            myView.EWOneTapGesture = self
        }else if taps == 2{
            myView.EWDoubleTapGesture = self
        }

    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    ///将外界传入的block传入手势方法
    fileprivate func registerHandler(_ handler:@escaping EWTapGestureHanler){
        self.tappedHandler.append(handler)
    }
    @objc func tapped(_ sender: UITapGestureRecognizer) {
        for handler in self.tappedHandler{
            handler()
        }
    }
}
///长按手势
class EWLongPressGesture {
    typealias EWLongPressGestureHandler = ()->Void
    fileprivate weak var myView:UIView!
    fileprivate let gesture : UILongPressGestureRecognizer
    fileprivate var tappedHandler = [EWLongPressGestureHandler]()

    init(view:UIView,taps:Int = 1) {
        myView = view
        gesture = UILongPressGestureRecognizer()
        gesture.minimumPressDuration = TimeInterval(taps)
        gesture.addTarget(self, action: #selector(EWTapGesture.tapped(_:)))
        myView.addGestureRecognizer(gesture)
        myView.EWLongTapGesture = self
    }
    ///将外界传入的block传入手势方法
    fileprivate func registerHandler(_ handler:@escaping EWLongPressGestureHandler){
        self.tappedHandler.append(handler)
    }
    @objc func tapped(_ sender: UITapGestureRecognizer) {
        for handler in self.tappedHandler{
            guard gesture.state == .began else { return }
            handler()
        }
    }
}
///滑动手势
class EWSwipeGesture {
    typealias EWSwipeGestureHandler = ()->Void
    fileprivate weak var myView:UIView!
    fileprivate let gesture : UISwipeGestureRecognizer
    fileprivate var tappedHandler = [EWSwipeGestureHandler]()

    init(view:UIView,direction: UISwipeGestureRecognizer.Direction = .up) {
        myView = view
        gesture = UISwipeGestureRecognizer()
        gesture.direction = direction
        gesture.addTarget(self, action: #selector(EWTapGesture.tapped(_:)))
        myView.addGestureRecognizer(gesture)
        switch direction {
        case .up:
            myView.EWUpSwipeGesture = self
        case .left:
            myView.EWLeftSwipeGesture = self
        case .right:
            myView.EWRightSwipeGesture = self
        case .down:
            myView.EWDownSwipeGesture = self
        default:
            return
        }
    }
    fileprivate func registerHandler(_ handler:@escaping EWSwipeGestureHandler){
        self.tappedHandler.append(handler)
    }
    @objc func tapped(_ sender: UITapGestureRecognizer) {
        for handler in self.tappedHandler{
            handler()
        }
    }
}

4.使用Extension为UIView进行拓展.

在这里让UIView遵循UIViewTapable协议,并使用RunTime为其增加手势属性.

 extension UIView: UIViewTapable {
    var tapHandlers: [EWTapGestureHanler]{
        return EWOneTapGesture.tappedHandler
    }
    var doubleTapGestureHandlers: [EWTapGestureHanler]{
        return EWDoubleTapGesture.tappedHandler
    }
    var longTapGestureHandlers: [EWTapGestureHanler]{
        return EWLongTapGesture.tappedHandler
    }
    var upSwipeGestureHandlers: [EWTapGestureHanler] {
        return EWUpSwipeGesture.tappedHandler
    }
    var leftSwipeGestureHandlers: [EWTapGestureHanler] {
        return EWLeftSwipeGesture.tappedHandler
    }
    var rightSwipeGestureHandlers: [EWTapGestureHanler] {
        return EWRightSwipeGesture.tappedHandler
    }
    var downSwipeGestureHandlers: [EWTapGestureHanler] {
        return EWDownSwipeGesture.tappedHandler
    }
    ///runtime的方式为View设置手势属性
    var EWOneTapGesture: EWTapGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWTapGestureKey) as? EWTapGesture {
                return obj
            }
            let tapGesture = EWTapGesture(view: self)
            tapGesture.gesture.require(toFail: EWDoubleTapGesture.gesture)
            return tapGesture
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWTapGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    var EWDoubleTapGesture: EWTapGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWDoubleTapGestureKey) as? EWTapGesture {
                return obj
            }
            return EWTapGesture(view: self,taps: 2)
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWDoubleTapGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    var EWLongTapGesture:EWLongPressGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWLongTapGestureKey) as? EWLongPressGesture {
                return obj
            }
            return EWLongPressGesture(view: self)
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWLongTapGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    var EWUpSwipeGesture: EWSwipeGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWUpSwipeGestureKey) as? EWSwipeGesture {
                return obj
            }
            return EWSwipeGesture(view: self)
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWUpSwipeGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    var EWLeftSwipeGesture: EWSwipeGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWLeftSwipeGestureKey) as? EWSwipeGesture {
                return obj
            }
            return EWSwipeGesture(view: self, direction: .left)
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWLeftSwipeGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    var EWRightSwipeGesture: EWSwipeGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWRightSwipeGestureKey) as? EWSwipeGesture {
                return obj
            }
            return EWSwipeGesture(view: self, direction: .right)
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWRightSwipeGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    var EWDownSwipeGesture: EWSwipeGesture {
        get {
            if let obj = objc_getAssociatedObject(self, EWGestureAssociatedObjectKey.EWDownSwipeGestureKey) as? EWSwipeGesture {
                return obj
            }
            return EWSwipeGesture(view: self, direction: .down)
        }
        set {
            objc_setAssociatedObject(self, EWGestureAssociatedObjectKey.EWDownSwipeGestureKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }

    func whenTapped(handler: @escaping () -> Void){
        self.isUserInteractionEnabled = true
        self.EWOneTapGesture.registerHandler(handler)
    }

    func whenDoubleTapped(handler:@escaping ()->Void){
        self.isUserInteractionEnabled = true
        self.EWDoubleTapGesture.registerHandler(handler)
    }

    func whenLongPressed(handler:@escaping ()->Void){
        self.isUserInteractionEnabled = true
        self.EWLongTapGesture.registerHandler(handler)
    }

    func whenUpSwiped(handler: @escaping () -> Void) {
        self.isUserInteractionEnabled = true
        self.EWUpSwipeGesture.registerHandler(handler)
    }

    func whenLeftSwiped(handler: @escaping () -> Void) {
        self.isUserInteractionEnabled = true
        self.EWLeftSwipeGesture.registerHandler(handler)
    }

    func whenRightSwiped(handler: @escaping () -> Void) {
        self.isUserInteractionEnabled = true
        self.EWRightSwipeGesture.registerHandler(handler)
    }

    func whenDownSwiped(handler: @escaping () -> Void) {
        self.isUserInteractionEnabled = true
        self.EWDownSwipeGesture.registerHandler(handler)
    }
}

使用方法:

将UIView+TappedExtension.swift文件拖入项目,调用时:

tapView.whenTapped {
    EWToast.showTopWithText(text: "点击事件", duration: 1)
}
tapView.whenUpSwiped {
    EWToast.showCenterWithText(text: "上滑事件", duration: 1)
}
tapView.whenLeftSwiped {
    EWToast.showCenterWithText(text: "左滑事件", duration: 1)
}
tapView.whenRightSwiped {
    EWToast.showCenterWithText(text: "右滑事件", duration: 1)
}
tapView.whenDownSwiped {
    EWToast.showCenterWithText(text: "下滑事件", duration: 1)
}
tapView.whenLongPressed {
    EWToast.showCenterWithText(text: "长按事件", duration: 1)
}
tapView.whenDoubleTapped {
    EWToast.showBottomWithText(text: "双击事件", duration: 1)
}

demo地址:EWViewTappedExtension

有问题欢迎探讨.

相关文章

网友评论

    本文标题:Swift.用RunTime和Extension的方式为UIVi

    本文链接:https://www.haomeiwen.com/subject/qplazftx.html