Adding a Closure as Target to a Uibutton

Adding a closure as target to a UIButton

Do Not Use This Answer, See Note Below

NOTE:
like @EthanHuang said
"This solution doesn't work if you have more than two instances. All actions will be overwrite by the last assignment."

Keep in mind this when you develop, i will post another solution soon.

If you want to add a closure as target to a UIButton, you must add a function to UIButton class by using extension

Swift 5

import UIKit    
extension UIButton {
private func actionHandler(action:(() -> Void)? = nil) {
struct __ { static var action :(() -> Void)? }
if action != nil { __.action = action }
else { __.action?() }
}
@objc private func triggerActionHandler() {
self.actionHandler()
}
func actionHandler(controlEvents control :UIControl.Event, ForAction action:@escaping () -> Void) {
self.actionHandler(action: action)
self.addTarget(self, action: #selector(triggerActionHandler), for: control)
}
}

Older

import UIKit

extension UIButton {
private func actionHandleBlock(action:(() -> Void)? = nil) {
struct __ {
static var action :(() -> Void)?
}
if action != nil {
__.action = action
} else {
__.action?()
}
}

@objc private func triggerActionHandleBlock() {
self.actionHandleBlock()
}

func actionHandle(controlEvents control :UIControlEvents, ForAction action:() -> Void) {
self.actionHandleBlock(action)
self.addTarget(self, action: "triggerActionHandleBlock", forControlEvents: control)
}
}

and the call:

 let button = UIButton()
button.actionHandle(controlEvents: .touchUpInside,
ForAction:{() -> Void in
print("Touch")
})

Weird behavior when I try to use a closure as the target of a UIButton

If you check the addTarget signature, you will see the following:

open func addTarget(_ target: Any?, action: Selector, for controlEvents: UIControl.Event)

First parameter target is Any?, so passing (Function) as target compiles fine. It even will work but can lead to weird issues, like opening keyboard will stop the button from calling the action.

Attaching Closure to UIButton (To design custom popup)

Few Issues...
1. action1 can't be local variable, Make it class variable
2. adding target to button is wrongly done.

Try this, I have fixed the issues...

final class Action: NSObject {        
private let _action: () -> ()
init(action: @escaping () -> ()) {
_action = action
super.init()
}

func action() {
_action()
}
}

Popup View

class Popup: UIView {        
//... your other code

var action1:Action?
func addTouch(_ leftAction : @escaping () -> ()){
action1 = Action.init(action: leftAction)
self.leftButton.addTarget(action1, action: #selector(Action.action), for: .touchUpInside)
}
}

Why am I getting this warning when I add the target to my UIButton in my controller? (the warning and code is stated below)

Use lazy var instead of let it will solve problem or set target in viewDidLoad.

Is there a way to respond to UIButton tap without using selectors?

You could create your own button subclass which wraps the selector syntax around a closure-based API.

class MyButton: UIButton {

var action: (() -> ())?

override init(frame: CGRect) {
super.init(frame: frame)
sharedInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedInit()
}

private func sharedInit() {
addTarget(self, action: #selector(touchUpInside), for: .touchUpInside)
}

@objc private func touchUpInside() {
action?()
}

}

Then to add an action to the button, you can just set the closure.

let button = MyButton()
button.action = {
print("hello")
}


Related Topics



Leave a reply



Submit