Skip to content

Commit 6aca514

Browse files
rostislav-simonikgrabbou
authored andcommitted
Add fix for refresh control state's race condition. (facebook#21763)
Summary: Fixes facebook#21762 Pull Request resolved: facebook#21763 Differential Revision: D14064621 Pulled By: cpojer fbshipit-source-id: 63010248a46cb49ed17ed89d7c55945aa7b22973
1 parent 7263a77 commit 6aca514

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

React/Views/RCTRefreshControl.m

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
@implementation RCTRefreshControl {
1313
BOOL _isInitialRender;
1414
BOOL _currentRefreshingState;
15+
UInt64 _currentRefreshingStateClock;
16+
UInt64 _currentRefreshingStateTimestamp;
1517
BOOL _refreshingProgrammatically;
1618
NSString *_title;
1719
UIColor *_titleColor;
@@ -21,6 +23,8 @@ - (instancetype)init
2123
{
2224
if ((self = [super init])) {
2325
[self addTarget:self action:@selector(refreshControlValueChanged) forControlEvents:UIControlEventValueChanged];
26+
_currentRefreshingStateClock = 1;
27+
_currentRefreshingStateTimestamp = 0;
2428
_isInitialRender = true;
2529
_currentRefreshingState = false;
2630
}
@@ -49,6 +53,7 @@ - (void)layoutSubviews
4953

5054
- (void)beginRefreshingProgrammatically
5155
{
56+
UInt64 beginRefreshingTimestamp = _currentRefreshingStateTimestamp;
5257
_refreshingProgrammatically = YES;
5358
// When using begin refreshing we need to adjust the ScrollView content offset manually.
5459
UIScrollView *scrollView = (UIScrollView *)self.superview;
@@ -62,7 +67,10 @@ - (void)beginRefreshingProgrammatically
6267
animations:^(void) {
6368
[scrollView setContentOffset:offset];
6469
} completion:^(__unused BOOL finished) {
65-
[super beginRefreshing];
70+
if(beginRefreshingTimestamp == self->_currentRefreshingStateTimestamp) {
71+
[super beginRefreshing];
72+
[self setCurrentRefreshingState:super.refreshing];
73+
}
6674
}];
6775
}
6876

@@ -72,14 +80,18 @@ - (void)endRefreshingProgrammatically
7280
// endRefreshing otherwise the next pull to refresh will not work properly.
7381
UIScrollView *scrollView = (UIScrollView *)self.superview;
7482
if (_refreshingProgrammatically && scrollView.contentOffset.y < 0) {
83+
UInt64 endRefreshingTimestamp = _currentRefreshingStateTimestamp;
7584
CGPoint offset = {scrollView.contentOffset.x, 0};
7685
[UIView animateWithDuration:0.25
7786
delay:0
7887
options:UIViewAnimationOptionBeginFromCurrentState
7988
animations:^(void) {
8089
[scrollView setContentOffset:offset];
8190
} completion:^(__unused BOOL finished) {
82-
[super endRefreshing];
91+
if(endRefreshingTimestamp == self->_currentRefreshingStateTimestamp) {
92+
[super endRefreshing];
93+
[self setCurrentRefreshingState:super.refreshing];
94+
}
8395
}];
8496
} else {
8597
[super endRefreshing];
@@ -120,7 +132,7 @@ - (void)_updateTitle
120132
- (void)setRefreshing:(BOOL)refreshing
121133
{
122134
if (_currentRefreshingState != refreshing) {
123-
_currentRefreshingState = refreshing;
135+
[self setCurrentRefreshingState:refreshing];
124136

125137
if (refreshing) {
126138
if (!_isInitialRender) {
@@ -132,9 +144,15 @@ - (void)setRefreshing:(BOOL)refreshing
132144
}
133145
}
134146

147+
- (void)setCurrentRefreshingState:(BOOL)refreshing
148+
{
149+
_currentRefreshingState = refreshing;
150+
_currentRefreshingStateTimestamp = _currentRefreshingStateClock++;
151+
}
152+
135153
- (void)refreshControlValueChanged
136154
{
137-
_currentRefreshingState = super.refreshing;
155+
[self setCurrentRefreshingState:super.refreshing];
138156
_refreshingProgrammatically = NO;
139157

140158
if (_onRefresh) {

0 commit comments

Comments
 (0)