My app requires to run a timer in the background continuously when an app is in the background and it should stop when app gets into the foreground.
The app is built with React Native and it doesn't have any proper module to run in the background yet. So I created a bridge between React Native Javascript and Native iOS.
I expose a ios native module can signal events to JavaScript without being invoked directly and passed an event to native code to invoke from javascript.
TestManager.h
//
// TestManager.h
//
// Created by Asbar Ali on 6/7/19.
// Copyright © 2019 Facebook. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
NS_ASSUME_NONNULL_BEGIN
@interface TestManager : RCTEventEmitter <RCTBridgeModule>
@end
NS_ASSUME_NONNULL_END
TestManager.m
//
// TestManager.m
// CrockfitMobile
//
// Created by Asbar Ali on 6/7/19.
// Copyright © 2019 Facebook. All rights reserved.
//
#import "TestManager.h"
@implementation TestManager
{
bool hasListeners;
}
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}
// Will be called when this module's first listener is added.
-(void)startObserving {
hasListeners = YES;
NSLog(@"Listener added");
}
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
hasListeners = NO;
NSLog(@"Listner Removed");
}
- (void)TestEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
if (hasListeners) { // Only send events if anyone is listening
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}
}
RCT_EXPORT_METHOD(timerStart:(NSString *)name location:(NSString *)location)
{
NSLog(@"invoked by javaScript");
}
@end
following method in TestManager.m is called from a React Native(JavaScript)
RCT_EXPORT_METHOD(timerStart:(NSString *)name location:(NSString *)location)
{
NSLog(@"invoked by javaScript");
}
When I add the following code inside the above method, NSTimer is not firing.
NOTE: This will work perfectly in ViewControllers
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:@selector(updateModel:) userInfo:str repeats:YES];
I found some answers for it. Answ1 Answ2
Then I realize that it could be a threading problem and need to call in the main thread.
How can I start a timer in subclass of RCTEventEmitter when app get into the background? (TestManager.m)
If we can't do it in this module, how can we do it?