fix (iOS): refresh control not behaving correctly if it is offscreen (#45996)

Summary:
FIXES https://github.com/facebook/react-native/issues/45858

When working with UIRefreshControl in a custom React Native component, we encountered a problem where the refresh control did not behave correctly if it was offscreen. Specifically, attempts to programmatically begin or end refreshing were ignored if the control was not visible. This typically manifested as the refresh control not updating its state properly when it was re-rendered or moved in the view hierarchy.
Happening only on old-arch.

**Problem Details**
**Offscreen Refresh Control Ignored:** The UIRefreshControl would ignore calls to beginRefreshing and endRefreshing if it was not currently visible on the screen.
**Inconsistent State:** The internal state _currentRefreshingState might not match the actual state of the UIRefreshControl, leading to unexpected behavior.

**Steps to Fix**
**Track Visibility with didMoveToWindow:**

Implement the didMoveToWindow method to track when the refresh control is added to or removed from the window.
Use a flag _hasMovedToWindow to keep track of this state.
And check this flag should be true whenever we start or end refreshing

## Changelog:

[IOS] [FIXED] - Fixed an issue where the refresh control would not behave correctly if it was offscreen.

Pull Request resolved: https://github.com/facebook/react-native/pull/45996

Test Plan:
Issue Screen recording

https://github.com/user-attachments/assets/73b45c27-19c2-4eeb-991e-33b45f0a6d97

Fix Screen Recording :

https://github.com/user-attachments/assets/ffc6b6e6-fc68-498c-abdf-3144c31caa86

Reviewed By: realsoelynn

Differential Revision: D61657472

Pulled By: cipolleschi

fbshipit-source-id: 7a369f8e3ca902536a7608fbe1b89cec7734c418
This commit is contained in:
Deepanshu.shukla
2024-08-23 04:50:46 -07:00
committed by Facebook GitHub Bot
parent 4075418c14
commit a8be335a37
@@ -22,6 +22,7 @@
NSString *_title;
UIColor *_titleColor;
CGFloat _progressViewOffset;
BOOL _hasMovedToWindow;
}
- (instancetype)init
@@ -32,6 +33,7 @@
_currentRefreshingStateTimestamp = 0;
_isInitialRender = true;
_currentRefreshingState = false;
_hasMovedToWindow = NO;
}
return self;
}
@@ -56,8 +58,22 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
_isInitialRender = false;
}
- (void)didMoveToWindow
{
[super didMoveToWindow];
if (self.window) {
_hasMovedToWindow = YES;
} else {
_hasMovedToWindow = NO;
}
}
- (void)beginRefreshingProgrammatically
{
if (!_hasMovedToWindow)
return;
UInt64 beginRefreshingTimestamp = _currentRefreshingStateTimestamp;
_refreshingProgrammatically = YES;
@@ -92,6 +108,8 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
- (void)endRefreshingProgrammatically
{
if (!_hasMovedToWindow)
return;
// The contentOffset of the scrollview MUST be greater than the contentInset before calling
// endRefreshing otherwise the next pull to refresh will not work properly.
UIScrollView *scrollView = self.scrollView;