Hooking up UIButton to closure? (Swift, target-action)

前端 未结 8 1810
滥情空心
滥情空心 2020-12-13 02:51

I want to hook up a UIButton to a piece of code – from what I have found, the preferred method to do this in Swift is still to use the addTarget(target: AnyObject?, ac

8条回答
  •  一整个雨季
    2020-12-13 03:08

    You can replace target-action with a closure by adding a helper closure wrapper (ClosureSleeve) and adding it as an associated object to the control so it gets retained.

    This is a similar solution to the one in n13's answer. But I find it simpler and more elegant. The closure is invoked more directly and the wrapper is automatically retained (added as an associated object).

    Swift 3 and 4

    class ClosureSleeve {
        let closure: () -> ()
    
        init(attachTo: AnyObject, closure: @escaping () -> ()) {
            self.closure = closure
            objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN)
        }
    
        @objc func invoke() {
            closure()
        }
    }
    
    extension UIControl {
        func addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) {
            let sleeve = ClosureSleeve(attachTo: self, closure: action)
            addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
        }
    }
    

    Usage:

    button.addAction {
        print("Hello")
    }
    

    It automatically hooks to the .primaryActionTriggered event which equals to .touchUpInside for UIButton.

提交回复
热议问题