From 3214677cb0f795ddeb52c1d4c7a23b1f6becaa11 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Mon, 29 Apr 2019 21:46:23 +0800 Subject: [PATCH 1/4] [iOS] Timing: Fixes timer when app get into background --- React/Modules/RCTTiming.m | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/React/Modules/RCTTiming.m b/React/Modules/RCTTiming.m index ef4ec94819e3eb..1ba839f0bd060c 100644 --- a/React/Modules/RCTTiming.m +++ b/React/Modules/RCTTiming.m @@ -97,6 +97,7 @@ @implementation RCTTiming NSTimer *_sleepTimer; BOOL _sendIdleEvents; BOOL _inBackground; + UIBackgroundTaskIdentifier _backgroundTaskIdentifier; } @synthesize bridge = _bridge; @@ -112,6 +113,7 @@ - (void)setBridge:(RCTBridge *)bridge _paused = YES; _timers = [NSMutableDictionary new]; _inBackground = NO; + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; for (NSString *name in @[UIApplicationWillResignActiveNotification, UIApplicationDidEnterBackgroundNotification, @@ -135,10 +137,19 @@ - (void)setBridge:(RCTBridge *)bridge - (void)dealloc { + [self markEndOfBackgroundTaskIfNeeded]; [_sleepTimer invalidate]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } +- (void)markEndOfBackgroundTaskIfNeeded +{ + if (_backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier]; + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } +} + - (dispatch_queue_t)methodQueue { return RCTJSThread; @@ -152,6 +163,17 @@ - (void)invalidate - (void)appDidMoveToBackground { + [self markEndOfBackgroundTaskIfNeeded]; + __weak typeof(self) weakSelf = self; + // Marks the beginning of a new long-running background task. We can run the timer in the background. + _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + typeof(self) strongSelf = weakSelf; + if (!strongSelf) { + return ; + } + // Mark the end of background task + [strongSelf markEndOfBackgroundTaskIfNeeded]; + }]; // Deactivate the CADisplayLink while in the background. [self stopTimers]; _inBackground = YES; @@ -163,6 +185,10 @@ - (void)appDidMoveToBackground - (void)appDidMoveToForeground { + if (self->_backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[UIApplication sharedApplication] endBackgroundTask:self->_backgroundTaskIdentifier]; + _backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } _inBackground = NO; [self startTimers]; } From 8e0b4120c29aa875d9a0dd87a2b07b986b53352a Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Tue, 30 Apr 2019 09:16:36 +0800 Subject: [PATCH 2/4] Code clean --- React/Modules/RCTTiming.m | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/React/Modules/RCTTiming.m b/React/Modules/RCTTiming.m index 1ba839f0bd060c..7a2f1c8fb25b95 100644 --- a/React/Modules/RCTTiming.m +++ b/React/Modules/RCTTiming.m @@ -185,10 +185,7 @@ - (void)appDidMoveToBackground - (void)appDidMoveToForeground { - if (self->_backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:self->_backgroundTaskIdentifier]; - _backgroundTaskIdentifier = UIBackgroundTaskInvalid; - } + [self markEndOfBackgroundTaskIfNeeded]; _inBackground = NO; [self startTimers]; } From fc47b35069a5a6a06442bc46100ff20e99b38836 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Wed, 1 May 2019 23:49:13 +0800 Subject: [PATCH 3/4] Fire background timer only if we have timer --- React/Modules/RCTTiming.m | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/React/Modules/RCTTiming.m b/React/Modules/RCTTiming.m index 7a2f1c8fb25b95..64aa39c89e8bef 100644 --- a/React/Modules/RCTTiming.m +++ b/React/Modules/RCTTiming.m @@ -142,6 +142,22 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } +- (void)markStartOfBackgroundTaskIfNeeded +{ + if (_backgroundTaskIdentifier == UIBackgroundTaskInvalid) { + __weak typeof(self) weakSelf = self; + // Marks the beginning of a new long-running background task. We can run the timer in the background. + _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + typeof(self) strongSelf = weakSelf; + if (!strongSelf) { + return ; + } + // Mark the end of background task + [strongSelf markEndOfBackgroundTaskIfNeeded]; + }]; + } +} + - (void)markEndOfBackgroundTaskIfNeeded { if (_backgroundTaskIdentifier != UIBackgroundTaskInvalid) { @@ -163,17 +179,6 @@ - (void)invalidate - (void)appDidMoveToBackground { - [self markEndOfBackgroundTaskIfNeeded]; - __weak typeof(self) weakSelf = self; - // Marks the beginning of a new long-running background task. We can run the timer in the background. - _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - typeof(self) strongSelf = weakSelf; - if (!strongSelf) { - return ; - } - // Mark the end of background task - [strongSelf markEndOfBackgroundTaskIfNeeded]; - }]; // Deactivate the CADisplayLink while in the background. [self stopTimers]; _inBackground = YES; @@ -283,6 +288,7 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update } if (_inBackground) { if (timerCount) { + [self markStartOfBackgroundTaskIfNeeded]; [self scheduleSleepTimer:nextScheduledTarget]; } } else if (!_sendIdleEvents && timersToCall.count == 0) { @@ -361,6 +367,7 @@ - (void)timerDidFire } if (_inBackground) { + [self markStartOfBackgroundTaskIfNeeded]; [self scheduleSleepTimer:timer.target]; } else if (_paused) { if ([timer.target timeIntervalSinceNow] > kMinimumSleepInterval) { From d38fea7f3eca6500cd896ecdbed8f429e4040b81 Mon Sep 17 00:00:00 2001 From: Christoph Nakazawa Date: Thu, 30 May 2019 08:50:20 +0100 Subject: [PATCH 4/4] Update RCTTiming.m --- React/Modules/RCTTiming.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/React/Modules/RCTTiming.m b/React/Modules/RCTTiming.m index 64aa39c89e8bef..7568dff8a58a8f 100644 --- a/React/Modules/RCTTiming.m +++ b/React/Modules/RCTTiming.m @@ -150,7 +150,7 @@ - (void)markStartOfBackgroundTaskIfNeeded _backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ typeof(self) strongSelf = weakSelf; if (!strongSelf) { - return ; + return; } // Mark the end of background task [strongSelf markEndOfBackgroundTaskIfNeeded];