Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Free to copy, use and modify for all types of software projects
- import UIKit
- // ************** Protocol ***************
- /// Closurable protocol
- protocol Closurable: class {}
- // restrict protocol to only classes => can refer to the class instance in the protocol extension
- extension Closurable {
- // Create container for closure, store it and return it
- func getContainer(for closure: @escaping (Self) -> Void) -> ClosureContainer<Self> {
- weak var weakSelf = self
- let container = ClosureContainer(closure: closure, caller: weakSelf)
- // store the container so that it can be called later, we do not need to explicitly retrieve it.
- objc_setAssociatedObject(self, Unmanaged.passUnretained(self).toOpaque(), container as AnyObject!, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- return container
- }
- }
- /// Container class for closures, so that closure can be stored as an associated object
- final class ClosureContainer<T: Closurable> {
- var closure: (T) -> Void
- var caller: T?
- init(closure: @escaping (T) -> Void, caller: T?) {
- self.closure = closure
- self.caller = caller
- }
- // method for the target action, visible to UIKit classes via @objc
- @objc func processHandler() {
- if let caller = caller {
- closure(caller)
- }
- }
- // target action
- var action: Selector { return #selector(processHandler) }
- }
- // ************** UIKit extensions ***************
- /// extension for UIButton - actions with closure
- extension UIButton: Closurable {
- func addTarget(forControlEvents: UIControlEvents = .touchUpInside, closure: @escaping (UIButton) -> Void) {
- let container = getContainer(for: closure)
- addTarget(container, action: container.action, for: forControlEvents)
- }
- }
- /// extension for UIPageControl - actions with closure
- extension UIPageControl: Closurable {
- func addTarget(forControlEvents: UIControlEvents = .valueChanged, closure: @escaping (UIPageControl) -> Void) {
- let container = getContainer(for: closure)
- addTarget(container, action: container.action, for: forControlEvents)
- }
- }
- /// extension for UIGestureRecognizer - actions with closure
- extension UIGestureRecognizer: Closurable {
- convenience init(closure: @escaping (UIGestureRecognizer) -> Void) {
- self.init()
- let container = getContainer(for: closure)
- addTarget(container, action: container.action)
- }
- }
- /// extension for UIBarButtonItem - actions with closure
- extension UIBarButtonItem: Closurable {
- convenience init(image: UIImage?, style: UIBarButtonItemStyle = .plain, closure: @escaping (UIBarButtonItem) -> Void) {
- self.init(image: image, style: style, target: nil, action: nil)
- let container = getContainer(for: closure)
- target = container
- action = container.action
- }
- convenience init(title: String?, style: UIBarButtonItemStyle = .plain, closure: @escaping (UIBarButtonItem) -> Void) {
- self.init(title: title, style: style, target: nil, action: nil)
- let container = getContainer(for: closure)
- target = container
- action = container.action
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement