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
How to Build For Armv6 and Armv7 Architectures With iOS 5
Displaying a Stock iOS Notification Banner When Your App Is Open and in the Foreground
Best Way to Check If Uitableviewcell Is Completely Visible
How to Make a Push Segue When a Uitableviewcell Is Selected
How to Use Uiview Autoresizingmask Property Programmatically
Opening View Controller from App Delegate Using Swift
Trying to Convert Firebase Timestamp to Nsdate in Swift
How to Make App Fully Working Correctly for Autorotation in iOS 6
How to Recognize Swipe in All 4 Directions
iOS (Iphone, iPad, Ipodtouch) View Real-Time Console Log Terminal
iOS 7 Status Bar with Phonegap
Auto Layout Constraints Issue on iOS7 in Uitableviewcell
Changing Root View Controller of a iOS Window