JLRefreshBasis.m 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. - (void)prepareInterface {
  32. self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  33. self.backgroundColor = [UIColor clearColor];
  34. self.jl_height = JLRefreshHeight;
  35. }
  36. - (void)layoutSubviews {
  37. [super layoutSubviews];
  38. self.jl_width = CGRectGetWidth(self.superview.frame);
  39. }
  40. //- (void)dealloc {
  41. // [self resignObserver];
  42. //}
  43. /**添加观察者*/
  44. - (void)registObserver {
  45. NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
  46. [_scrollView addObserver:self forKeyPath:JLRefreshKeyPathContentOffset options:options context:nil];
  47. [_scrollView addObserver:self forKeyPath:JLRefreshKeyPathContentSize options:options context:nil];
  48. _pan = _scrollView.panGestureRecognizer;
  49. [_pan addObserver:self forKeyPath:JLRefreshKeyPathState options:options context:nil];
  50. }
  51. /**移除观察者*/
  52. - (void)resignObserver {
  53. /** fix crash while exit viewcontroller <Exception: NSInternalInconsistencyException>
  54. * self.superview == _scrollview
  55. * but superview is readonly ,while invoke this method,the _scrollview has been dealloced,then it get a wild pointer
  56. * if we use self.superview to get the object that is nil
  57. */
  58. [self.superview removeObserver:self forKeyPath:JLRefreshKeyPathContentOffset];
  59. [self.superview removeObserver:self forKeyPath:JLRefreshKeyPathContentSize];
  60. [_pan removeObserver:self forKeyPath:JLRefreshKeyPathState];
  61. _pan = nil;
  62. }
  63. - (void)willMoveToSuperview:(UIView *)newSuperview {
  64. [super willMoveToSuperview:newSuperview];
  65. [self resignObserver];
  66. if (newSuperview == nil) {
  67. _scrollView = nil;
  68. return;
  69. }
  70. // 父控件不是ScrollView,不做设置
  71. if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) {
  72. _scrollView = nil;
  73. return;
  74. }
  75. _scrollView = (UIScrollView *)newSuperview;
  76. _scrollView.alwaysBounceVertical = YES; // 永远支持垂直弹簧效果
  77. self.state = JLRefreshStateIdle;
  78. self.scrollViewOriginInsetTop = _scrollView.jl_insetTop;
  79. self.scrollViewOriginInsetBottom = _scrollView.jl_insetBottom;
  80. [self registObserver];
  81. }
  82. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
  83. if (!self.isUserInteractionEnabled) {
  84. return;
  85. }
  86. if (keyPath == JLRefreshKeyPathContentSize) {
  87. [self scrollViewContentSizeDidChange:change];
  88. }
  89. if (self.hidden) {
  90. return;
  91. }
  92. if (keyPath == JLRefreshKeyPathContentOffset) {
  93. [self scrollViewContentOffsetDidChange:change];
  94. }
  95. if (keyPath == JLRefreshKeyPathState) {
  96. [self scrollViewPanGestureStateDidChange:change];
  97. }
  98. }
  99. - (void)scrollViewContentSizeDidChange:(NSDictionary<NSKeyValueChangeKey,id> *)change {
  100. }
  101. - (void)scrollViewContentOffsetDidChange:(NSDictionary<NSKeyValueChangeKey,id> *)change {
  102. }
  103. - (void)scrollViewPanGestureStateDidChange:(NSDictionary<NSKeyValueChangeKey,id> *)change {
  104. }
  105. - (void)setState:(JLRefreshState)state {
  106. _state = state;
  107. }
  108. - (void)endRefresh {
  109. self.state = JLRefreshStateIdle;
  110. }
  111. @end