JLRefreshBasis.m 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. //
  2. // JLRefresh.m
  3. // JLRefreshDemo
  4. //
  5. // Created by Jack on 2017/3/3.
  6. // Copyright © 2017年 mini1. All rights reserved.
  7. //
  8. #import "JLRefreshBasis.h"
  9. NSTimeInterval const JLRefreshDuration = 0.25;
  10. CGFloat const JLRefreshHeight = 64;
  11. NSString *const JLRefreshKeyPathContentOffset = @"contentOffset";
  12. NSString *const JLRefreshKeyPathContentSize = @"contentSize";
  13. NSString *const JLRefreshKeyPathContentInset = @"contentInset";
  14. NSString *const JLRefreshKeyPathState = @"state";
  15. @interface JLRefreshBasis ()
  16. {
  17. __weak UIScrollView *_scrollView;
  18. UIPanGestureRecognizer *_pan;
  19. }
  20. @property (nonatomic,assign) CGFloat scrollViewOriginInsetTop;
  21. @property (nonatomic,assign) CGFloat scrollViewOriginInsetBottom;
  22. @end
  23. @implementation JLRefreshBasis
  24. - (instancetype)initWithFrame:(CGRect)frame {
  25. if (self = [super initWithFrame:frame]) {
  26. [self prepareInterface];
  27. self.state = JLRefreshStateIdle;
  28. }
  29. return self;
  30. }
  31. - (NSString *)refreshTitleForState:(JLRefreshState)state {
  32. return nil;
  33. }
  34. - (void)prepareInterface {
  35. self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  36. self.backgroundColor = [UIColor clearColor];
  37. self.jl_height = JLRefreshHeight;
  38. }
  39. - (void)layoutSubviews {
  40. [super layoutSubviews];
  41. self.jl_width = CGRectGetWidth(self.superview.frame);
  42. }
  43. //- (void)dealloc {
  44. // [self resignObserver];
  45. //}
  46. /**添加观察者*/
  47. - (void)registObserver {
  48. NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
  49. [_scrollView addObserver:self forKeyPath:JLRefreshKeyPathContentOffset options:options context:nil];
  50. [_scrollView addObserver:self forKeyPath:JLRefreshKeyPathContentSize options:options context:nil];
  51. _pan = _scrollView.panGestureRecognizer;
  52. [_pan addObserver:self forKeyPath:JLRefreshKeyPathState options:options context:nil];
  53. }
  54. /**移除观察者*/
  55. - (void)resignObserver {
  56. /** fix crash while exit viewcontroller <Exception: NSInternalInconsistencyException>
  57. * self.superview == _scrollview
  58. * but superview is readonly ,while invoke this method,the _scrollview has been dealloced,then it get a wild pointer
  59. * if we use self.superview to get the object that is nil
  60. */
  61. [self.superview removeObserver:self forKeyPath:JLRefreshKeyPathContentOffset];
  62. [self.superview removeObserver:self forKeyPath:JLRefreshKeyPathContentSize];
  63. [_pan removeObserver:self forKeyPath:JLRefreshKeyPathState];
  64. _pan = nil;
  65. }
  66. - (void)willMoveToSuperview:(UIView *)newSuperview {
  67. [super willMoveToSuperview:newSuperview];
  68. [self resignObserver];
  69. if (newSuperview == nil) {
  70. _scrollView = nil;
  71. return;
  72. }
  73. // 父控件不是ScrollView,不做设置
  74. if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) {
  75. _scrollView = nil;
  76. return;
  77. }
  78. _scrollView = (UIScrollView *)newSuperview;
  79. _scrollView.alwaysBounceVertical = YES; // 永远支持垂直弹簧效果
  80. self.state = JLRefreshStateIdle;
  81. self.scrollViewOriginInsetTop = _scrollView.jl_insetTop;
  82. self.scrollViewOriginInsetBottom = _scrollView.jl_insetBottom;
  83. [self registObserver];
  84. }
  85. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
  86. if (!self.isUserInteractionEnabled) {
  87. return;
  88. }
  89. if (keyPath == JLRefreshKeyPathContentSize) {
  90. [self scrollViewContentSizeDidChange:change];
  91. }
  92. if (self.hidden) {
  93. return;
  94. }
  95. if (keyPath == JLRefreshKeyPathContentOffset) {
  96. [self scrollViewContentOffsetDidChange:change];
  97. }
  98. if (keyPath == JLRefreshKeyPathState) {
  99. [self scrollViewPanGestureStateDidChange:change];
  100. }
  101. }
  102. - (void)scrollViewContentSizeDidChange:(NSDictionary<NSKeyValueChangeKey,id> *)change {
  103. }
  104. - (void)scrollViewContentOffsetDidChange:(NSDictionary<NSKeyValueChangeKey,id> *)change {
  105. }
  106. - (void)scrollViewPanGestureStateDidChange:(NSDictionary<NSKeyValueChangeKey,id> *)change {
  107. }
  108. - (void)setState:(JLRefreshState)state {
  109. _state = state;
  110. }
  111. - (void)endRefresh {
  112. self.state = JLRefreshStateIdle;
  113. }
  114. @end