Last active
July 31, 2019 23:44
-
-
Save lidio601/983cfb4e3793322e1955eaab569ba715 to your computer and use it in GitHub Desktop.
React Native - native module started kit (iOs)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ... | |
#import "FooModule.h" | |
// ... | |
@interface AppDelegate () | |
// ... | |
@property (nonatomic, strong) FooModule *fooModule; | |
// ... | |
@end | |
@implementation AppDelegate | |
// ... | |
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions | |
{ | |
// ... | |
self.fooModule = [FooModule bootstrap]; | |
// ... | |
} | |
// ... | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FooModule.h | |
// | |
// Created by Fabio Cigliano on 1/08/19. | |
// | |
#import <Foundation/Foundation.h> | |
#import <React/RCTBridgeModule.h> | |
#import <React/RCTEventEmitter.h> | |
#define MODULE_NAME @"Foo" | |
#define EVENT_NAME @"change" | |
#define MLOG_FORMAT @"[foo] :: %s [Line %d] " | |
#define MLog(fmt, ...) NSLog((MLOG_FORMAT fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); | |
NS_ASSUME_NONNULL_BEGIN | |
@interface FooModule : RCTEventEmitter <RCTBridgeModule> | |
+ (id) bootstrap; | |
@end | |
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// FooModule.m | |
// | |
// Created by Fabio Cigliano on 1/08/19. | |
// | |
#import "FooModule.h" | |
@interface FooModule (RCTEventEmitter) | |
@end | |
@interface FooModule () | |
{ | |
} | |
@property (nonatomic, assign) NSDate* lastUpdate; | |
@property (nonatomic, assign) BOOL isListening; | |
@property (nonatomic, assign) int listenerCount; | |
- (void)attachListener; | |
- (void)removeListener; | |
-(BOOL)hasListener; | |
@end | |
@implementation FooModule : RCTEventEmitter | |
#pragma mark - External | |
+ (id) bootstrap { | |
MLog(@"initialized"); | |
return [[FooModule alloc] init]; | |
} | |
#pragma mark - Internal | |
- (instancetype)init | |
{ | |
self = [super init]; | |
if (self) { | |
// init internal state | |
self.lastUpdate = nil; | |
self.isListening = NO; | |
self.listenerCount = 0; | |
// should we start any service at startup? | |
// [self attachListener]; | |
} | |
return self; | |
} | |
- (void)dealloc | |
{ | |
// remove any service | |
[self removeListener]; | |
} | |
#pragma mark - State | |
// expose the internal state | |
- (NSDictionary*) getStateObject { | |
return @{ | |
@"lastUpdate": @([self.lastUpdate timeIntervalSince1970]) | |
}; | |
} | |
#pragma mark - React | |
RCT_EXPORT_MODULE(ScreenStateModule); | |
+ (BOOL)requiresMainQueueSetup | |
{ | |
return NO; | |
} | |
#pragma mark - Exported | |
RCT_EXPORT_METHOD(getState:(RCTResponseSenderBlock)callback) | |
{ | |
callback(@[ [self getStateObject] ]); | |
} | |
#pragma mark - Event handling | |
- (NSArray<NSString *> *)supportedEvents | |
{ | |
return @[ EVENT_NAME ]; | |
} | |
// Will be called when this module's first listener is added. | |
-(void)startObserving { | |
// Set up any upstream listeners or background tasks as necessary | |
self.listenerCount++; | |
[self attachListener]; | |
} | |
// Will be called when this module's last listener is removed, or on dealloc. | |
-(void)stopObserving { | |
// Remove upstream listeners, stop unnecessary background tasks | |
self.listenerCount--; | |
if (self.listenerCount <= 0) { | |
[self attachListener]; | |
} | |
} | |
-(BOOL)hasListener { | |
return self.bridge != nil && self.listenerCount > 0; | |
} | |
#pragma mark - Services | |
- (void) attachListener | |
{ | |
if (self.isListening) { | |
// skip this if already listening | |
return; | |
} | |
self.isListening = YES; | |
MLog(@"attachListener"); | |
// | |
// TODO: add your service here | |
// | |
/* | |
for instance | |
// listen for lock state changes | |
notify_register_dispatch("com.apple.springboard.lockstate", &lockStateToken, dispatch_get_main_queue(), ^(int token) { | |
// here we forward events to js | |
[self readState]; | |
}); | |
*/ | |
// at startup read and forward the state | |
[self readState]; | |
} | |
- (void) removeListener | |
{ | |
if (!self.isListening) { | |
// skip this if already stopped | |
return; | |
} | |
self.isListening = NO; | |
MLog(@"removeListener"); | |
// | |
// TODO: add your service here | |
// | |
} | |
- (void) readState | |
{ | |
BOOL didChange = NO; | |
// | |
// TODO: do something here | |
// | |
// trigger all the attached event listener | |
if ([self hasListener] && didChange) { | |
self.lastUpdate = [NSDate date]; | |
NSDictionary* state = [self getStateObject]; | |
MLog(@"new event %@", state); | |
[self sendEventWithName:EVENT_NAME body:state]; | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment