Advertisement
Guest User

Untitled

a guest
Mar 20th, 2019
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.97 KB | None | 0 0
  1. // Free to copy, use and modify for all types of software projects
  2.  
  3. import UIKit
  4.  
  5. // ************** Protocol ***************
  6. /// Closurable protocol
  7. protocol Closurable: class {}
  8. // restrict protocol to only classes => can refer to the class instance in the protocol extension
  9. extension Closurable {
  10.  
  11. // Create container for closure, store it and return it
  12. func getContainer(for closure: @escaping (Self) -> Void) -> ClosureContainer<Self> {
  13. weak var weakSelf = self
  14. let container = ClosureContainer(closure: closure, caller: weakSelf)
  15. // store the container so that it can be called later, we do not need to explicitly retrieve it.
  16. objc_setAssociatedObject(self, Unmanaged.passUnretained(self).toOpaque(), container as AnyObject!, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  17. return container
  18. }
  19. }
  20.  
  21. /// Container class for closures, so that closure can be stored as an associated object
  22. final class ClosureContainer<T: Closurable> {
  23.  
  24. var closure: (T) -> Void
  25. var caller: T?
  26.  
  27. init(closure: @escaping (T) -> Void, caller: T?) {
  28. self.closure = closure
  29. self.caller = caller
  30. }
  31.  
  32. // method for the target action, visible to UIKit classes via @objc
  33. @objc func processHandler() {
  34. if let caller = caller {
  35. closure(caller)
  36. }
  37. }
  38.  
  39. // target action
  40. var action: Selector { return #selector(processHandler) }
  41. }
  42.  
  43. // ************** UIKit extensions ***************
  44. /// extension for UIButton - actions with closure
  45. extension UIButton: Closurable {
  46.  
  47. func addTarget(forControlEvents: UIControlEvents = .touchUpInside, closure: @escaping (UIButton) -> Void) {
  48. let container = getContainer(for: closure)
  49. addTarget(container, action: container.action, for: forControlEvents)
  50. }
  51. }
  52.  
  53. /// extension for UIPageControl - actions with closure
  54. extension UIPageControl: Closurable {
  55.  
  56. func addTarget(forControlEvents: UIControlEvents = .valueChanged, closure: @escaping (UIPageControl) -> Void) {
  57. let container = getContainer(for: closure)
  58. addTarget(container, action: container.action, for: forControlEvents)
  59. }
  60. }
  61.  
  62. /// extension for UIGestureRecognizer - actions with closure
  63. extension UIGestureRecognizer: Closurable {
  64.  
  65. convenience init(closure: @escaping (UIGestureRecognizer) -> Void) {
  66. self.init()
  67. let container = getContainer(for: closure)
  68. addTarget(container, action: container.action)
  69. }
  70. }
  71.  
  72. /// extension for UIBarButtonItem - actions with closure
  73. extension UIBarButtonItem: Closurable {
  74.  
  75. convenience init(image: UIImage?, style: UIBarButtonItemStyle = .plain, closure: @escaping (UIBarButtonItem) -> Void) {
  76. self.init(image: image, style: style, target: nil, action: nil)
  77. let container = getContainer(for: closure)
  78. target = container
  79. action = container.action
  80. }
  81.  
  82. convenience init(title: String?, style: UIBarButtonItemStyle = .plain, closure: @escaping (UIBarButtonItem) -> Void) {
  83. self.init(title: title, style: style, target: nil, action: nil)
  84. let container = getContainer(for: closure)
  85. target = container
  86. action = container.action
  87. }
  88. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement