UIBarButtonItem+FixSpace.swift 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. //
  2. // UIBarButtonItem+FixSpace.swift
  3. // SwiftBilibili
  4. //
  5. // Created by 罗文 on 2021/3/9.
  6. // Copyright © 2021年 罗文. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. extension NSObject {
  11. static func swizzleMethod(_ cls: AnyClass, originalSelector: Selector, swizzleSelector: Selector){
  12. let originalMethod = class_getInstanceMethod(cls, originalSelector)!
  13. let swizzledMethod = class_getInstanceMethod(cls, swizzleSelector)!
  14. let didAddMethod = class_addMethod(cls,
  15. originalSelector,
  16. method_getImplementation(swizzledMethod),
  17. method_getTypeEncoding(swizzledMethod))
  18. if didAddMethod {
  19. class_replaceMethod(cls,
  20. swizzleSelector,
  21. method_getImplementation(originalMethod),
  22. method_getTypeEncoding(originalMethod))
  23. } else {
  24. method_exchangeImplementations(originalMethod,
  25. swizzledMethod)
  26. }
  27. }
  28. }
  29. //extension UIApplication {
  30. // private static let classSwizzedMethod: Void = {
  31. // UINavigationController.sx_initialize
  32. // if #available(iOS 11.0, *) {
  33. // UINavigationBar.sx_initialize
  34. // }
  35. // }()
  36. //
  37. // open override var next: UIResponder? {
  38. // UIApplication.classSwizzedMethod
  39. // return super.next
  40. // }
  41. //}
  42. var sx_defultFixSpace: CGFloat = 5
  43. var sx_disableFixSpace: Bool = false
  44. extension UINavigationController {
  45. private struct AssociatedKeys {
  46. static var tempDisableFixSpace = "tempDisableFixSpace"
  47. static var tempBehavor = "tempBehavor"
  48. }
  49. static let sx_initialize: Void = {
  50. DispatchQueue.once(UUID().uuidString) {
  51. swizzleMethod(UINavigationController.self,
  52. originalSelector: #selector(UINavigationController.viewDidLoad),
  53. swizzleSelector: #selector(UINavigationController.sx_viewDidLoad))
  54. swizzleMethod(UINavigationController.self,
  55. originalSelector: #selector(UINavigationController.viewWillAppear(_:)),
  56. swizzleSelector: #selector(UINavigationController.sx_viewWillAppear(_:)))
  57. swizzleMethod(UINavigationController.self,
  58. originalSelector: #selector(UINavigationController.viewWillDisappear(_:)),
  59. swizzleSelector: #selector(UINavigationController.sx_viewWillDisappear(_:)))
  60. }
  61. }()
  62. private var tempDisableFixSpace: Bool {
  63. get {
  64. return objc_getAssociatedObject(self, &AssociatedKeys.tempDisableFixSpace) as? Bool ?? false
  65. }
  66. set {
  67. objc_setAssociatedObject(self, &AssociatedKeys.tempDisableFixSpace, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  68. }
  69. }
  70. @available(iOS 11.0, *)
  71. private var tempBehavor: UIScrollView.ContentInsetAdjustmentBehavior {
  72. get {
  73. return objc_getAssociatedObject(self, &AssociatedKeys.tempBehavor) as? UIScrollView.ContentInsetAdjustmentBehavior ?? .automatic
  74. }
  75. set {
  76. objc_setAssociatedObject(self, &AssociatedKeys.tempBehavor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
  77. }
  78. }
  79. @objc private func sx_viewDidLoad() {
  80. disableFixSpace(true, with: true)
  81. sx_viewDidLoad()
  82. }
  83. @objc private func sx_viewWillAppear(_ animated: Bool) {
  84. disableFixSpace(true, with: false)
  85. sx_viewWillAppear(animated)
  86. }
  87. @objc private func sx_viewWillDisappear(_ animated: Bool) {
  88. disableFixSpace(false, with: true)
  89. sx_viewWillDisappear(animated)
  90. }
  91. private func disableFixSpace(_ disable: Bool, with temp: Bool) {
  92. if type(of: self) == UIImagePickerController.self {
  93. if disable == true {
  94. if temp { tempDisableFixSpace = sx_disableFixSpace }
  95. sx_disableFixSpace = true
  96. if #available(iOS 11.0, *) {
  97. tempBehavor = UIScrollView.appearance().contentInsetAdjustmentBehavior
  98. UIScrollView.appearance().contentInsetAdjustmentBehavior = .automatic
  99. }
  100. } else {
  101. sx_disableFixSpace = tempDisableFixSpace
  102. if #available(iOS 11.0, *) {
  103. UIScrollView.appearance().contentInsetAdjustmentBehavior = tempBehavor
  104. }
  105. }
  106. }
  107. }
  108. }
  109. @available(iOS 11.0, *)
  110. extension UINavigationBar {
  111. static let sx_initialize: Void = {
  112. DispatchQueue.once(UUID().uuidString) {
  113. swizzleMethod(UINavigationBar.self,
  114. originalSelector: #selector(UINavigationBar.layoutSubviews),
  115. swizzleSelector: #selector(UINavigationBar.sx_layoutSubviews))
  116. }
  117. }()
  118. @objc func sx_layoutSubviews() {
  119. sx_layoutSubviews()
  120. if sx_disableFixSpace == false {
  121. layoutMargins = .zero
  122. let space = sx_defultFixSpace
  123. for view in subviews {
  124. if NSStringFromClass(view.classForCoder).contains("ContentView") {
  125. view.layoutMargins = UIEdgeInsets(top: 0, left: space, bottom: 0, right: space)
  126. }
  127. }
  128. }
  129. }
  130. }
  131. extension UINavigationItem {
  132. private enum BarButtonItem: String {
  133. case left = "_leftBarButtonItem"
  134. case right = "_rightBarButtonItem"
  135. }
  136. open override func setValue(_ value: Any?, forKey key: String) {
  137. if #available(iOS 11.0, *) {
  138. super.setValue(value, forKey: key)
  139. } else {
  140. if sx_disableFixSpace == false && (key == BarButtonItem.left.rawValue || key == BarButtonItem.right.rawValue) {
  141. guard let item = value as? UIBarButtonItem else {
  142. super.setValue(value, forKey: key)
  143. return
  144. }
  145. let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
  146. space.width = sx_defultFixSpace - 16
  147. if key == BarButtonItem.left.rawValue {
  148. leftBarButtonItems = [space, item]
  149. } else {
  150. rightBarButtonItems = [space, item]
  151. }
  152. } else {
  153. super.setValue(value, forKey: key)
  154. }
  155. }
  156. }
  157. }