GTMRefreshComponent.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. //
  2. // GTMRefreshComponent.swift
  3. // GTMRefresh
  4. //
  5. // Created by luoyang on 2016/12/7.
  6. // Copyright © 2016年 luoyang. All rights reserved.
  7. //
  8. import UIKit
  9. /// 状态枚举
  10. ///
  11. /// - idle: 闲置
  12. /// - pulling: 可以进行刷新
  13. /// - refreshing: 正在刷新
  14. /// - willRefresh: 即将刷新
  15. /// - noMoreData: 没有更多数据
  16. public enum GTMRefreshState {
  17. case idle // 闲置
  18. case pulling // 可以进行刷新
  19. case refreshing // 正在刷新
  20. case willRefresh // 即将刷新
  21. case noMoreData // 没有更多数据
  22. }
  23. public protocol SubGTMRefreshComponentProtocol {
  24. func scollViewContentOffsetDidChange(change: [NSKeyValueChangeKey : Any]?)
  25. func scollViewContentSizeDidChange(change: [NSKeyValueChangeKey : Any]?)
  26. }
  27. open class GTMRefreshComponent: UIView {
  28. public weak var scrollView: UIScrollView?
  29. public var scrollViewOriginalInset: UIEdgeInsets?
  30. var state: GTMRefreshState = .idle
  31. // MARK: Life Cycle
  32. override init(frame: CGRect) {
  33. super.init(frame: frame)
  34. setup()
  35. }
  36. required public init?(coder aDecoder: NSCoder) {
  37. super.init(coder: aDecoder)
  38. setup()
  39. }
  40. func setup() {
  41. self.autoresizingMask = UIView.AutoresizingMask.flexibleWidth
  42. self.backgroundColor = UIColor.clear
  43. self.state = .idle
  44. }
  45. override open func draw(_ rect: CGRect) {
  46. super.draw(rect)
  47. if self.state == .willRefresh {
  48. // 预防view还没显示出来就调用了beginRefreshing
  49. self.state = .refreshing
  50. }
  51. }
  52. deinit {
  53. if GTMRefreshConstant.debug { print("GTMRefreshComponent excute deinit() ... ")}
  54. }
  55. override open func willMove(toSuperview newSuperview: UIView?) {
  56. super.willMove(toSuperview: newSuperview)
  57. guard let scrollView = newSuperview as? UIScrollView else {
  58. return
  59. }
  60. self.mj_x = 0
  61. self.mj_w = scrollView.mj_w
  62. self.scrollView = scrollView
  63. // 设置永远支持垂直弹簧效果
  64. self.scrollView?.alwaysBounceVertical = true
  65. self.scrollViewOriginalInset = scrollView.mj_inset
  66. }
  67. open override func willMove(toWindow newWindow: UIWindow?) {
  68. super.willMove(toWindow: newWindow)
  69. if newWindow != nil {
  70. self.addObserver()
  71. } else {
  72. self.removeAbserver()
  73. }
  74. }
  75. // MARK: KVO
  76. private func addObserver() {
  77. if GTMRefreshConstant.debug { print("GTMRefresh -> addObserver ... ")}
  78. scrollView?.addObserver(self, forKeyPath: GTMRefreshConstant.keyPathContentOffset, options: .new, context: nil)
  79. scrollView?.addObserver(self, forKeyPath: GTMRefreshConstant.keyPathContentSize, options: .new, context: nil)
  80. }
  81. private func removeAbserver() {
  82. if GTMRefreshConstant.debug { print("GTMRefresh -> removeAbserver ... ")}
  83. scrollView?.removeObserver(self, forKeyPath: GTMRefreshConstant.keyPathContentOffset)
  84. scrollView?.removeObserver(self, forKeyPath: GTMRefreshConstant.keyPathContentSize)
  85. }
  86. override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  87. guard isUserInteractionEnabled else {
  88. return
  89. }
  90. if let sub: SubGTMRefreshComponentProtocol = self as? SubGTMRefreshComponentProtocol {
  91. if keyPath == GTMRefreshConstant.keyPathContentSize {
  92. sub.scollViewContentSizeDidChange(change: change)
  93. }
  94. if self.isHidden {
  95. return
  96. }
  97. if keyPath == GTMRefreshConstant.keyPathContentOffset {
  98. sub.scollViewContentOffsetDidChange(change: change)
  99. }
  100. }
  101. }
  102. }