Advertisement
Guest User

Untitled

a guest
Feb 21st, 2019
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.15 KB | None | 0 0
  1. import UIKit
  2.  
  3. @objc protocol StatusBarAnimatable where Self: UIViewController {
  4. var isAnimatableHiding: Bool { get }
  5. var statusBarAnimatableAnimationDuration: TimeInterval { get }
  6. var statusBarAnimatableUpdateAnimation: UIStatusBarAnimation { get }
  7. @objc optional var isAnimatableAfterInteractivity: Bool { get }
  8. }
  9.  
  10. private let swizzling: (AnyClass, Selector, Selector) -> Void = { forClass, originalSelector, swizzledSelector in
  11. let originalMethod = class_getInstanceMethod(forClass, originalSelector)!
  12. let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector)!
  13. method_exchangeImplementations(originalMethod, swizzledMethod)
  14. }
  15.  
  16. extension UIViewController {
  17. static func doSwizzle() {
  18. do {
  19. let originalSelector = #selector(viewWillAppear(_:))
  20. let swizzledSelector = #selector(swizzled_viewWillAppear(_:))
  21. swizzling(UIViewController.self, originalSelector, swizzledSelector)
  22. }
  23.  
  24. do {
  25. let originalSelector = #selector(viewDidDisappear(_:))
  26. let swizzledSelector = #selector(swizzled_viewDidDisappear(_:))
  27. swizzling(UIViewController.self, originalSelector, swizzledSelector)
  28. }
  29.  
  30. do {
  31. let originalSelector = #selector(getter: preferredStatusBarUpdateAnimation)
  32. let swizzledSelector = #selector(getter: swizzled_preferredStatusBarUpdateAnimation)
  33. swizzling(UIViewController.self, originalSelector, swizzledSelector)
  34. }
  35. }
  36.  
  37. @objc func swizzled_viewWillAppear(_ animated: Bool) {
  38. self.swizzled_viewWillAppear(animated)
  39. if let avc = self as? StatusBarAnimatable {
  40. avc.performViewWillAppear()
  41. }
  42. }
  43.  
  44. @objc func swizzled_viewDidDisappear(_ animated: Bool) {
  45. self.swizzled_viewDidDisappear(animated)
  46. if let avc = self as? StatusBarAnimatable {
  47. avc.performViewDidDisappear()
  48. }
  49. }
  50.  
  51. // swiftlint:disable:next identifier_name
  52. @objc var swizzled_preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
  53. if let avc = self as? StatusBarAnimatable {
  54. return avc.statusBarAnimatableUpdateAnimation
  55. } else {
  56. return self.swizzled_preferredStatusBarUpdateAnimation
  57. }
  58. }
  59. }
  60.  
  61. private var key: Void?
  62.  
  63. extension StatusBarAnimatable {
  64. var shouldHideStatusBar: Bool {
  65. get {
  66. return (objc_getAssociatedObject(self, &key) as? Bool) ?? UIApplication.shared.isStatusBarHidden
  67. }
  68.  
  69. set {
  70. objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  71. }
  72. }
  73.  
  74. fileprivate func performViewWillAppear() {
  75. guard let coordinator = transitionCoordinator else { return }
  76. let onlyAfterNonInteractive = isAnimatableAfterInteractivity ?? true
  77. if onlyAfterNonInteractive && coordinator.initiallyInteractive {
  78. coordinator.notifyWhenInteractionChanges { [unowned self] (ctx) in
  79. if ctx.isCancelled { return }
  80. self.shouldHideStatusBar = self.isAnimatableHiding
  81. UIView.animate(withDuration: self.statusBarAnimatableAnimationDuration) {
  82. self.setNeedsStatusBarAppearanceUpdate()
  83. }
  84. }
  85. } else {
  86. coordinator.animate(alongsideTransition: { [unowned self] (_) in
  87. self.shouldHideStatusBar = self.isAnimatableHiding
  88. UIView.animate(withDuration: self.statusBarAnimatableAnimationDuration) {
  89. self.setNeedsStatusBarAppearanceUpdate()
  90. }
  91. })
  92. }
  93. }
  94.  
  95. fileprivate func performViewDidDisappear() {
  96. self.shouldHideStatusBar = UIApplication.shared.isStatusBarHidden
  97. }
  98. }
  99.  
  100. import UIKit
  101.  
  102. struct StatusBarAnimatableConfig {
  103. let isPrefersHidden: Bool
  104. let animation: UIStatusBarAnimation
  105. let animationDuration: TimeInterval?
  106. let isAnimatableAfterInteractivity: Bool
  107. }
  108.  
  109. extension StatusBarAnimatableConfig {
  110. init(isPrefersHidden: Bool, animation: UIStatusBarAnimation) {
  111. self.init(isPrefersHidden: isPrefersHidden,
  112. animation: animation,
  113. animationDuration: nil,
  114. isAnimatableAfterInteractivity: true)
  115. }
  116. }
  117.  
  118. class StatusBarAnimatableViewController: UIViewController {
  119. private var shouldCurrentlyHideStatusBar = false
  120.  
  121. override func viewWillAppear(_ animated: Bool) {
  122. super.viewWillAppear(animated)
  123. guard let coordinator = transitionCoordinator else { return }
  124. let config = statusBarAnimatableConfig
  125. let onlyAfterNonInteractive = config.isAnimatableAfterInteractivity
  126. if onlyAfterNonInteractive && coordinator.initiallyInteractive {
  127. coordinator.notifyWhenInteractionChanges { ctx in
  128. guard !ctx.isCancelled else { return }
  129. self.shouldCurrentlyHideStatusBar = config.isPrefersHidden
  130. UIView.animate(withDuration: config.animationDuration ?? ctx.transitionDuration) {
  131. self.setNeedsStatusBarAppearanceUpdate()
  132. }
  133. }
  134. } else {
  135. coordinator.animate(alongsideTransition: { ctx in
  136. self.shouldCurrentlyHideStatusBar = config.isPrefersHidden
  137. UIView.animate(withDuration: config.animationDuration ?? ctx.transitionDuration) {
  138. self.setNeedsStatusBarAppearanceUpdate()
  139. }
  140. })
  141. }
  142. }
  143.  
  144. override func viewDidDisappear(_ animated: Bool) {
  145. super.viewDidDisappear(animated)
  146. shouldCurrentlyHideStatusBar = UIApplication.shared.isStatusBarHidden
  147. }
  148.  
  149. final override var prefersStatusBarHidden: Bool {
  150. return shouldCurrentlyHideStatusBar
  151. }
  152.  
  153. final override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
  154. return statusBarAnimatableConfig.animation
  155. }
  156.  
  157. open var statusBarAnimatableConfig: StatusBarAnimatableConfig {
  158. return StatusBarAnimatableConfig(isPrefersHidden: false,
  159. animation: .none)
  160. }
  161. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement