实现UIButton通过闭包添加事件

作者: _kk_ | 来源:发表于2016-11-02 15:36 被阅读471次

    要实现的效果如下:

    btn.addTarget(for: .touchUpInside) { (sender) in
                print("button click!")
            }
    

    很多时候我们的的button点击事件就一行代码,而这一行代码还需要另写一个方法。然后用selector给button。这样:


    Snip20161102_1.png

    当代码量增大,按钮的点击事件和按钮的定义就分散在代码的不同区域,给后期的代码维护造成不便。为了解决这个问题,我给UIButton扩展了一个用尾随闭包给按钮添加事件的方法。然后代码变成这样:


    Snip20161102_2.png
    显然要代码集中了,也好好看了!

    实现:

    想法:给UIButton扩展一个方法带闭包参数的方法,在这个方法中去调用系统的addTraget方法,并把闭包保存起来,在addTraget中Selector对应的方法去执行闭包。

    实现步骤:

    1、在extension中给UIButton扩展一个带尾随闭包添加事件的方法:

    func addTarget(for controlEvents: UIControlEvents,action:@escaping (UIButton)->())
    {
    }
    

    在该方法中,要做两件事:
    一、是给按钮添加响应事件,这个没啥可说的,直接调用系统API。
    二、是把闭包保存起来,以便于在响应事件方法中去执行闭包。怎么保存呢,只能通过一个属性保存。extension扩展属性,用到runtime的关联属性方法。直接写一个闭包属性去保存事件闭包:


    Snip20161102_3.png

    写是没问题,但一运行就会错误,通过实验,发现关联对象不支持基本数据类型,和闭包类型(具体原因我也没弄清楚,等搞清楚再修改过此处)。

    鉴于这种情况,定义了一个结构体,在结构体中定义了一个闭包属性。关联一个该结构体类型的对象。问题便迎刃而解。
    下面是全部扩展代码:

    extension UIButton{
        
        struct AssociatedClosureClass {
            var eventClosure: (UIButton)->()
        }
    
        private struct AssociatedKeys {
            static var eventClosureObj:AssociatedClosureClass?
        }
        
        private var eventClosureObj: AssociatedClosureClass{
            set{
                objc_setAssociatedObject(self, &AssociatedKeys.eventClosureObj, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                
            }
            get{
                return (objc_getAssociatedObject(self, &AssociatedKeys.eventClosureObj) as? AssociatedClosureClass)!
            }
        }
     
        func addTarget(for controlEvents: UIControlEvents,action:@escaping (UIButton)->()) {
            let eventObj = AssociatedClosureClass(eventClosure: action)
            eventClosureObj = eventObj
            addTarget(self, action: #selector(eventExcuate(_:)), for: controlEvents)
            
        }
        
        @objc private func eventExcuate(_ sender: UIButton){
            eventClosureObj.eventClosure(sender)
        }
    }
    
    

    同理,我们可以写监听通知,timer执行,segement切换的方法扩展。

    如果你有更好的想法,或者能解答文中问题,希望看到你的留言。

    相关文章

      网友评论

        本文标题:实现UIButton通过闭包添加事件

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