Skip to content

Commit e1d03b4

Browse files
radko93facebook-github-bot
authored andcommitted
Reverts "Timing: Fixes timer when app get into background (#24649)" (#27073)
Summary: This PR reverts commit 3382984 that is causing #26696 #26995. > app would be closed immediately after going to background on iOS 13.1/13.2 and was investigated by minhtc #26696 (comment). The commit that is being reverted is apparently causing the app to be closed immediately. This has to be reverted in master separately as the file differs there. Similar PR for 0.61. branch #27065 ## Changelog [iOS] [Fixed] - Fix apps crashing on iOS 13.x when running timer in the background Pull Request resolved: #27073 Test Plan: Try [this](3382984#commitcomment-35745287) snippet on iOS 13.1/13.2, the app should not crash anymore Differential Revision: D18323679 Pulled By: cpojer fbshipit-source-id: 3af7036a0e1d3811924e581c649b16e5a4667e83
1 parent 1df8bd4 commit e1d03b4

File tree

1 file changed

+38
-70
lines changed

1 file changed

+38
-70
lines changed

React/CoreModules/RCTTiming.mm

+38-70
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
#import <React/RCTAssert.h>
1313
#import <React/RCTBridge+Private.h>
1414
#import <React/RCTBridge.h>
15+
#import <React/RCTConvert.h>
1516
#import <React/RCTLog.h>
1617
#import <React/RCTUtils.h>
17-
#import <React/RCTConvert.h>
1818

1919
#import "CoreModulesPlugins.h"
2020

@@ -75,8 +75,7 @@ @interface _RCTTimingProxy : NSObject
7575
@end
7676

7777
// NSTimer retains its target, insert this class to break potential retain cycles
78-
@implementation _RCTTimingProxy
79-
{
78+
@implementation _RCTTimingProxy {
8079
__weak id _target;
8180
}
8281

@@ -96,16 +95,14 @@ - (void)timerDidFire
9695

9796
@end
9897

99-
@interface RCTTiming() <NativeTimingSpec>
98+
@interface RCTTiming () <NativeTimingSpec>
10099
@end
101100

102-
@implementation RCTTiming
103-
{
101+
@implementation RCTTiming {
104102
NSMutableDictionary<NSNumber *, _RCTTimer *> *_timers;
105103
NSTimer *_sleepTimer;
106104
BOOL _sendIdleEvents;
107105
BOOL _inBackground;
108-
UIBackgroundTaskIdentifier _backgroundTaskIdentifier;
109106
id<RCTTimingDelegate> _timingDelegate;
110107
}
111108

@@ -115,7 +112,7 @@ @implementation RCTTiming
115112

116113
RCT_EXPORT_MODULE()
117114

118-
- (instancetype)initWithDelegate:(id<RCTTimingDelegate>) delegate
115+
- (instancetype)initWithDelegate:(id<RCTTimingDelegate>)delegate
119116
{
120117
if (self = [super init]) {
121118
[self setup];
@@ -136,19 +133,19 @@ - (void)setup
136133
_paused = YES;
137134
_timers = [NSMutableDictionary new];
138135
_inBackground = NO;
139-
_backgroundTaskIdentifier = UIBackgroundTaskInvalid;
140136

141-
for (NSString *name in @[UIApplicationWillResignActiveNotification,
142-
UIApplicationDidEnterBackgroundNotification,
143-
UIApplicationWillTerminateNotification]) {
137+
for (NSString *name in @[
138+
UIApplicationWillResignActiveNotification,
139+
UIApplicationDidEnterBackgroundNotification,
140+
UIApplicationWillTerminateNotification
141+
]) {
144142
[[NSNotificationCenter defaultCenter] addObserver:self
145143
selector:@selector(appDidMoveToBackground)
146144
name:name
147145
object:nil];
148146
}
149147

150-
for (NSString *name in @[UIApplicationDidBecomeActiveNotification,
151-
UIApplicationWillEnterForegroundNotification]) {
148+
for (NSString *name in @[ UIApplicationDidBecomeActiveNotification, UIApplicationWillEnterForegroundNotification ]) {
152149
[[NSNotificationCenter defaultCenter] addObserver:self
153150
selector:@selector(appDidMoveToForeground)
154151
name:name
@@ -158,34 +155,9 @@ - (void)setup
158155

159156
- (void)dealloc
160157
{
161-
[self markEndOfBackgroundTaskIfNeeded];
162158
[_sleepTimer invalidate];
163159
}
164160

165-
- (void)markStartOfBackgroundTaskIfNeeded
166-
{
167-
if (_backgroundTaskIdentifier == UIBackgroundTaskInvalid) {
168-
__weak RCTTiming *weakSelf = self;
169-
// Marks the beginning of a new long-running background task. We can run the timer in the background.
170-
_backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"rct.timing.gb.task" expirationHandler:^{
171-
RCTTiming *strongSelf = weakSelf;
172-
if (!strongSelf) {
173-
return;
174-
}
175-
// Mark the end of background task
176-
[strongSelf markEndOfBackgroundTaskIfNeeded];
177-
}];
178-
}
179-
}
180-
181-
- (void)markEndOfBackgroundTaskIfNeeded
182-
{
183-
if (_backgroundTaskIdentifier != UIBackgroundTaskInvalid) {
184-
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
185-
_backgroundTaskIdentifier = UIBackgroundTaskInvalid;
186-
}
187-
}
188-
189161
- (dispatch_queue_t)methodQueue
190162
{
191163
return RCTJSThread;
@@ -211,7 +183,6 @@ - (void)appDidMoveToBackground
211183

212184
- (void)appDidMoveToForeground
213185
{
214-
[self markEndOfBackgroundTaskIfNeeded];
215186
_inBackground = NO;
216187
[self startTimers];
217188
}
@@ -246,7 +217,7 @@ - (void)startTimers
246217

247218
- (BOOL)hasPendingTimers
248219
{
249-
@synchronized (_timers) {
220+
@synchronized(_timers) {
250221
return _sendIdleEvents || _timers.count > 0;
251222
}
252223
}
@@ -256,7 +227,7 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
256227
NSDate *nextScheduledTarget = [NSDate distantFuture];
257228
NSMutableArray<_RCTTimer *> *timersToCall = [NSMutableArray new];
258229
NSDate *now = [NSDate date]; // compare all the timers to the same base time
259-
@synchronized (_timers) {
230+
@synchronized(_timers) {
260231
for (_RCTTimer *timer in _timers.allValues) {
261232
if ([timer shouldFire:now]) {
262233
[timersToCall addObject:timer];
@@ -272,7 +243,7 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
272243
return [a.target compare:b.target];
273244
}] valueForKey:@"callbackID"];
274245
if (_bridge) {
275-
[_bridge enqueueJSCall:@"JSTimers" method:@"callTimers" args:@[sortedTimers] completion:NULL];
246+
[_bridge enqueueJSCall:@"JSTimers" method:@"callTimers" args:@[ sortedTimers ] completion:NULL];
276247
} else {
277248
[_timingDelegate callTimers:sortedTimers];
278249
}
@@ -283,7 +254,7 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
283254
[timer reschedule];
284255
nextScheduledTarget = [nextScheduledTarget earlierDate:timer.target];
285256
} else {
286-
@synchronized (_timers) {
257+
@synchronized(_timers) {
287258
[_timers removeObjectForKey:timer.callbackID];
288259
}
289260
}
@@ -294,25 +265,23 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
294265
NSTimeInterval frameElapsed = currentTimestamp - update.timestamp;
295266
if (kFrameDuration - frameElapsed >= kIdleCallbackFrameDeadline) {
296267
NSNumber *absoluteFrameStartMS = @((currentTimestamp - frameElapsed) * 1000);
297-
if (_bridge){
298-
[_bridge enqueueJSCall:@"JSTimers" method:@"callIdleCallbacks" args:@[absoluteFrameStartMS] completion:NULL];
268+
if (_bridge) {
269+
[_bridge enqueueJSCall:@"JSTimers" method:@"callIdleCallbacks" args:@[ absoluteFrameStartMS ] completion:NULL];
299270
} else {
300271
[_timingDelegate callIdleCallbacks:absoluteFrameStartMS];
301272
}
302-
303273
}
304274
}
305275

306276
// Switch to a paused state only if we didn't call any timer this frame, so if
307277
// in response to this timer another timer is scheduled, we don't pause and unpause
308278
// the displaylink frivolously.
309279
NSUInteger timerCount;
310-
@synchronized (_timers) {
280+
@synchronized(_timers) {
311281
timerCount = _timers.count;
312282
}
313283
if (_inBackground) {
314284
if (timerCount) {
315-
[self markStartOfBackgroundTaskIfNeeded];
316285
[self scheduleSleepTimer:nextScheduledTarget];
317286
}
318287
} else if (!_sendIdleEvents && timersToCall.count == 0) {
@@ -331,13 +300,13 @@ - (void)didUpdateFrame:(RCTFrameUpdate *)update
331300

332301
- (void)scheduleSleepTimer:(NSDate *)sleepTarget
333302
{
334-
@synchronized (self) {
303+
@synchronized(self) {
335304
if (!_sleepTimer || !_sleepTimer.valid) {
336305
_sleepTimer = [[NSTimer alloc] initWithFireDate:sleepTarget
337-
interval:0
338-
target:[_RCTTimingProxy proxyWithTarget:self]
339-
selector:@selector(timerDidFire)
340-
userInfo:nil
306+
interval:0
307+
target:[_RCTTimingProxy proxyWithTarget:self]
308+
selector:@selector(timerDidFire)
309+
userInfo:nil
341310
repeats:NO];
342311
[[NSRunLoop currentRunLoop] addTimer:_sleepTimer forMode:NSDefaultRunLoopMode];
343312
} else {
@@ -367,13 +336,14 @@ - (void)timerDidFire
367336
* calculating the timer's target time. We calculate this by passing in
368337
* Date.now() from JS and then subtracting that from the current time here.
369338
*/
370-
RCT_EXPORT_METHOD(createTimer:(double)callbackID
371-
duration:(NSTimeInterval)jsDuration
372-
jsSchedulingTime:(double)jsSchedulingTime
373-
repeats:(BOOL)repeats)
339+
RCT_EXPORT_METHOD(createTimer
340+
: (double)callbackID duration
341+
: (NSTimeInterval)jsDuration jsSchedulingTime
342+
: (double)jsSchedulingTime repeats
343+
: (BOOL)repeats)
374344
{
375345
NSNumber *callbackIdObjc = [NSNumber numberWithDouble:callbackID];
376-
NSDate *schedulingTime = [RCTConvert NSDate:[NSNumber numberWithDouble: jsSchedulingTime]];
346+
NSDate *schedulingTime = [RCTConvert NSDate:[NSNumber numberWithDouble:jsSchedulingTime]];
377347
if (jsDuration == 0 && repeats == NO) {
378348
// For super fast, one-off timers, just enqueue them immediately rather than waiting a frame.
379349
if (_bridge) {
@@ -384,10 +354,7 @@ - (void)timerDidFire
384354
return;
385355
}
386356

387-
[self createTimerForNextFrame:callbackIdObjc
388-
duration:jsDuration
389-
jsSchedulingTime:schedulingTime
390-
repeats:repeats];
357+
[self createTimerForNextFrame:callbackIdObjc duration:jsDuration jsSchedulingTime:schedulingTime repeats:repeats];
391358
}
392359

393360
/**
@@ -410,12 +377,11 @@ - (void)createTimerForNextFrame:(nonnull NSNumber *)callbackID
410377
interval:jsDuration
411378
targetTime:targetTime
412379
repeats:repeats];
413-
@synchronized (_timers) {
380+
@synchronized(_timers) {
414381
_timers[callbackID] = timer;
415382
}
416383

417384
if (_inBackground) {
418-
[self markStartOfBackgroundTaskIfNeeded];
419385
[self scheduleSleepTimer:timer.target];
420386
} else if (_paused) {
421387
if ([timer.target timeIntervalSinceNow] > kMinimumSleepInterval) {
@@ -426,17 +392,17 @@ - (void)createTimerForNextFrame:(nonnull NSNumber *)callbackID
426392
}
427393
}
428394

429-
RCT_EXPORT_METHOD(deleteTimer:(double)timerID)
395+
RCT_EXPORT_METHOD(deleteTimer : (double)timerID)
430396
{
431-
@synchronized (_timers) {
397+
@synchronized(_timers) {
432398
[_timers removeObjectForKey:[NSNumber numberWithDouble:timerID]];
433399
}
434400
if (![self hasPendingTimers]) {
435401
[self stopTimers];
436402
}
437403
}
438404

439-
RCT_EXPORT_METHOD(setSendIdleEvents:(BOOL)sendIdleEvents)
405+
RCT_EXPORT_METHOD(setSendIdleEvents : (BOOL)sendIdleEvents)
440406
{
441407
_sendIdleEvents = sendIdleEvents;
442408
if (sendIdleEvents) {
@@ -446,13 +412,15 @@ - (void)createTimerForNextFrame:(nonnull NSNumber *)callbackID
446412
}
447413
}
448414

449-
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
415+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:
416+
(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
450417
{
451418
return std::make_shared<facebook::react::NativeTimingSpecJSI>(self, jsInvoker);
452419
}
453420

454421
@end
455422

456-
Class RCTTimingCls(void) {
423+
Class RCTTimingCls(void)
424+
{
457425
return RCTTiming.class;
458426
}

0 commit comments

Comments
 (0)