Skip to content

Instantly share code, notes, and snippets.

@wh1pch81n
Last active September 3, 2016 04:18
Show Gist options
  • Save wh1pch81n/7e36ac05e7a2ca345975c09ed3344662 to your computer and use it in GitHub Desktop.
Save wh1pch81n/7e36ac05e7a2ca345975c09ed3344662 to your computer and use it in GitHub Desktop.
UIButton uses an old objective-c style method to add new callbacks which requires selectors. If you would rather use a block based approach then consider the following approach. You can specify a swift closure to be executed when the button receives a touch event.
///////////////
// code example
//-------------
button.callback { _ in
print("hello world") // print "hello world" when touchUpInside event is recieved
}
button.callback(for: [.TouchDown]) { _ in
print("hello world") // print "hello world" when touchDownInside event is recieved
}
button.callback(for: [.TouchUpInside, .TouchDown]) { _ in
print("hello world2") // print "hello world2" when touchUpInside OR touchDownInside event are recieved
}
////////
// code
//------
extension UIButton {
// a proxy class
internal class DHTargetActionProxy: UIView {
// a block that will be called
internal var _action: (AnyObject) -> ()
internal init(controlEvents: UIControlEvents, action: (AnyObject) -> ()) {
_action = action
super.init(frame: CGRect.zero)
self.tag = Int(controlEvents.rawValue)
}
internal required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
internal func action(sender: AnyObject) {
_action(sender)
}
}
public func callback(`for`controlEvents: UIControlEvents = [UIControlEvents.TouchUpInside],
action: (AnyObject) -> ())
{
// An array of supported touch events
let ctrlEvts: [UIControlEvents] =
[
.TouchDown,
.TouchDownRepeat,
.TouchDragInside,
.TouchDragOutside,
.TouchDragEnter,
.TouchDragExit,
.TouchUpInside,
.TouchUpOutside,
.TouchCancel,
.ValueChanged,
.EditingDidBegin,
.EditingChanged,
.EditingDidEnd,
.EditingDidEndOnExit
]
ctrlEvts.forEach {
if controlEvents.contains($0) {
// each touch event requires its own proxy object
_addActionToView($0.rawValue, action: action)
}
}
}
private func _addActionToView(tag: UInt, action: (AnyObject) -> ()) {
let foo = DHTargetActionProxy(controlEvents: UIControlEvents(rawValue: tag), action: action)
// remove previous if it exists
viewWithTag(Int(tag))?.removeFromSuperview()
// since foo is not retained by target(_, action:, forControlEvents:) we must save it somewhere. This implementation saves it as a subview.
self.addSubview(foo)
// add target to button. Target instance is a proxy object and it calls a selector beloing to that proxy object.
addTarget(foo, action: #selector(DHTargetActionProxy.action(_:)), forControlEvents: UIControlEvents(rawValue: tag))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment