@@ -11,6 +11,16 @@ import UIKit
1111public enum Position {
1212
1313 case top, bottom
14+
15+ var opposite : Position {
16+ switch self {
17+ case . top:
18+ return . bottom
19+ case . bottom:
20+ return . top
21+ }
22+ }
23+
1424}
1525
1626open class PullToRefresh : NSObject {
@@ -25,7 +35,17 @@ open class PullToRefresh: NSObject {
2535 open var shouldBeVisibleWhileScrolling : Bool = false
2636
2737 let refreshView : UIView
28- var action : ( ( ) -> ( ) ) ?
38+ var isEnabled : Bool = false {
39+ didSet{
40+ refreshView. isHidden = !isEnabled
41+ if isEnabled {
42+ addScrollViewObserving ( )
43+ } else {
44+ removeScrollViewObserving ( )
45+ }
46+ }
47+ }
48+ var action : ( ( ) -> Void ) ?
2949
3050 weak var scrollView : UIScrollView ? {
3151 willSet {
@@ -74,9 +94,12 @@ open class PullToRefresh: NSObject {
7494 scrollView? . contentInset = self . scrollViewDefaultInsets
7595 state = . initial
7696 }
77-
97+ case . releasing( progress: let value) where value < 0.1 :
98+ state = . initial
99+
78100 default : break
79101 }
102+ self . enableOppositeRefresher ( state == . initial)
80103 }
81104 }
82105
@@ -192,18 +215,30 @@ extension PullToRefresh {
192215extension PullToRefresh {
193216
194217 func startRefreshing( ) {
195- guard state == . initial, let scrollView = scrollView else {
218+ guard !isOppositeRefresherLoading , state == . initial, let scrollView = scrollView else {
196219 return
197220 }
221+
222+ let topInset : CGFloat = {
223+ if #available( iOS 11 , * ) {
224+ return scrollView. safeAreaInsets. top
225+ }
226+ return 0
227+ } ( )
228+
198229 var offsetY : CGFloat
199230 switch position {
200231 case . top:
201- offsetY = - refreshView . frame . height - scrollViewDefaultInsets. top
202- if #available( iOS 11 , * ) {
203- offsetY -= scrollView. safeAreaInsets. top
204- }
232+ offsetY = - refreshView . frame . height - scrollViewDefaultInsets. top - topInset
205233 case . bottom:
206- offsetY = scrollView. contentSize. height + refreshView. frame. height + scrollViewDefaultInsets. bottom - scrollView. bounds. height
234+ if scrollView. contentSize. height + refreshView. frame. height > scrollView. frame. height {
235+ offsetY = scrollView. contentSize. height
236+ + refreshView. frame. height
237+ + scrollViewDefaultInsets. bottom
238+ - scrollView. bounds. height
239+ } else {
240+ offsetY = 0 - topInset
241+ }
207242 }
208243 state = . loading
209244 scrollView. setContentOffset ( CGPoint ( x: 0 , y: offsetY) , animated: true )
@@ -219,8 +254,21 @@ extension PullToRefresh {
219254// MARK: - Animate scroll view
220255private extension PullToRefresh {
221256
257+ var isOppositeRefresherLoading : Bool {
258+ guard let scrollView = scrollView, let oppositeRefresher = scrollView. refresher ( at: position. opposite) else {
259+ return false
260+ }
261+ return oppositeRefresher. state != . initial
262+ }
263+
264+ func enableOppositeRefresher( _ enable: Bool ) {
265+ if let scrollView = scrollView, let oppositeRefresher = scrollView. refresher ( at: position. opposite) {
266+ oppositeRefresher. isEnabled = enable
267+ }
268+ }
269+
222270 func animateLoadingState( ) {
223- guard let scrollView = scrollView else {
271+ guard !isOppositeRefresherLoading , let scrollView = scrollView else {
224272 return
225273 }
226274
@@ -238,15 +286,14 @@ private extension PullToRefresh {
238286 let insetY = self . refreshView. frame. height + self . scrollViewDefaultInsets. bottom
239287 scrollView. contentInset. bottom = insetY
240288 }
241- } ,
289+ } ,
242290 completion: { _ in
243291 scrollView. bounces = true
244292 if self . shouldBeVisibleWhileScrolling {
245293 self . bringRefreshViewToSuperview ( )
246294 }
247- }
295+ }
248296 )
249-
250297 action ? ( )
251298 }
252299
@@ -260,11 +307,11 @@ private extension PullToRefresh {
260307 options: animationOptions,
261308 animations: {
262309 self . scrollView? . contentInset = self . scrollViewDefaultInsets
263- } ,
310+ } ,
264311 completion: { _ in
265312 self . addScrollViewObserving ( )
266313 self . state = . initial
267- }
314+ }
268315 )
269316 }
270317}
0 commit comments