EventEimtter - iOS
此篇需求:若收到APNs token時,需要通知React Native JS code
要用到的有以下檔案
APNsTokenEmitter.h - EventEmitter的標頭檔
APNsTokenEmitter.m - EventEmitter 實作
Use.h - 要暴露給JS Code使用的標頭檔)
Use.m(要使用的.m檔案內) - 要暴露給RN JS Code使用的實作(這邊我是把EventEmitter封裝進此檔案內
rnJsCode.js (RN的JS code) - 使用EventEimtter的JS Code
新建檔案(New File) APNsTokenEmitter.h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@interface APNsTokenEmitter : RCTEventEmitter<RCTBridgeModule>
- (void)apnsTokenReceive:(NSString *)token;
@end
新建檔案(New File) APNsTokenEmitter.m
#import "APNsTokenEmitter.h"
#import <React/RCTLog.h>
@implementation APNsTokenEmitter
{
bool hasListeners;
}
RCT_EXPORT_MODULE();
/**
想再其它.m檔內使用,得先取得APNsTokenEmitter,但用下方方法初始化會有Error
APNsTokenEmitter * tokenEmitter = [[APNsTokenEmitter alloc] init];
請參考 https://github.com/facebook/react-native/issues/15421 解法(singleton pattern)
**/
+ (id)allocWithZone:(NSZone *)zone {
static APNsTokenEmitter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [super allocWithZone:zone];
});
return sharedInstance;
}
-(NSArray<NSString *> *)supportedEvents
{
return @[@"APNsToken"];
}
// Will be called when this module's first listener is added.
-(void)startObserving {
RCTLogInfo(@"APNsTokenEmitter startObserving");
hasListeners = YES;
// Set up any upstream listeners or background tasks as necessary
}
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
RCTLogInfo(@"APNsTokenEmitter stopObserving");
hasListeners = NO;
// Remove upstream listeners, stop unnecessary background tasks
}
-(void)apnsTokenReceive:(NSString *)token
{
if (hasListeners) {
[self sendEventWithName:@"APNsToken" body:token];
RCTLogInfo(@"APNsTokenEmitter apnsTokenReceive(Has Listener), %@", token);
}else {
RCTLogInfo(@"APNsTokenEmitterapnsTokenReceive(No Listener), %@", token);
}
}
@end
要使用的.m檔案內
#import "AppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import “APNsTokenEmitter.h"
@implementation AppDelegate
...
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)token
{
//將token parser好
NSString * deviceTokenString = [[[[token description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
//pass deviceTokenString to function and sending events to javascript
[self sendAPNsTokenToJS:deviceTokenString];
}
//call APNsTokenEmitter
-(void)sendAPNsTokenToJS:(NSString *)token
{
APNsTokenEmitter *tokenEmitter = [APNsTokenEmitter allocWithZone:nil];
[tokenEmitter apnsTokenReceive:token];
}
....
@end
JS code
import { NativeEventEmitter, NativeModules } from 'react-native'
const {APNsTokenEmitter} = NativeModules
...
componentDidMount() {
this.eventEmitter = new NativeEventEmitter(NativeModules.APNsTokenEmitter);
this.eventEmitter.addListener('APNsToken', (token) => console.log(`token來也~~${token}`))
}
...
componentWillUnmount() {
subscription.remove();
}
參考
Last updated