GT2/Ejectable/node_modules/@unimodules/react-native-adapter/ios/UMReactNativeAdapter/Services/UMReactNativeEventEmitter.m

146 lines
4.4 KiB
Objective-C

// Copyright 2018-present 650 Industries. All rights reserved.
#import <UMReactNativeAdapter/UMReactNativeEventEmitter.h>
#import <UMCore/UMEventEmitter.h>
#import <UMCore/UMExportedModule.h>
#import <UMCore/UMModuleRegistry.h>
@interface UMReactNativeEventEmitter ()
@property (nonatomic, assign) int listenersCount;
@property (nonatomic, weak) UMModuleRegistry *umModuleRegistry;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *modulesListenersCounts;
@end
@implementation UMReactNativeEventEmitter
- (instancetype)init
{
if (self = [super init]) {
_listenersCount = 0;
_modulesListenersCounts = [NSMutableDictionary dictionary];
}
return self;
}
UM_REGISTER_MODULE();
+ (NSString *)moduleName
{
return @"UMReactNativeEventEmitter";
}
+ (const NSArray<Protocol *> *)exportedInterfaces
{
return @[@protocol(UMEventEmitterService)];
}
- (NSArray<NSString *> *)supportedEvents
{
NSMutableSet<NSString *> *eventsAccumulator = [NSMutableSet set];
for (UMExportedModule *exportedModule in [_umModuleRegistry getAllExportedModules]) {
if ([exportedModule conformsToProtocol:@protocol(UMEventEmitter)]) {
id<UMEventEmitter> eventEmitter = (id<UMEventEmitter>)exportedModule;
[eventsAccumulator addObjectsFromArray:[eventEmitter supportedEvents]];
}
}
return [eventsAccumulator allObjects];
}
RCT_EXPORT_METHOD(addProxiedListener:(NSString *)moduleName eventName:(NSString *)eventName)
{
[self addListener:eventName];
// Validate module
UMExportedModule *module = [_umModuleRegistry getExportedModuleForName:moduleName];
if (RCT_DEBUG && module == nil) {
UMLogError(@"Module for name `%@` has not been found.", moduleName);
return;
} else if (RCT_DEBUG && ![module conformsToProtocol:@protocol(UMEventEmitter)]) {
UMLogError(@"Module `%@` is not an UMEventEmitter, thus it cannot be subscribed to.", moduleName);
return;
}
// Validate eventEmitter
id<UMEventEmitter> eventEmitter = (id<UMEventEmitter>)module;
if (RCT_DEBUG && ![[eventEmitter supportedEvents] containsObject:eventName]) {
UMLogError(@"`%@` is not a supported event type for %@. Supported events are: `%@`",
eventName, moduleName, [[eventEmitter supportedEvents] componentsJoinedByString:@"`, `"]);
}
// Global observing state
_listenersCount += 1;
if (_listenersCount == 1) {
[self startObserving];
}
// Per-module observing state
int newModuleListenersCount = [self moduleListenersCountFor:moduleName] + 1;
if (newModuleListenersCount == 1) {
[eventEmitter startObserving];
}
_modulesListenersCounts[moduleName] = [NSNumber numberWithInt:newModuleListenersCount];
}
RCT_EXPORT_METHOD(removeProxiedListeners:(NSString *)moduleName count:(double)count)
{
[self removeListeners:count];
// Validate module
UMExportedModule *module = [_umModuleRegistry getExportedModuleForName:moduleName];
if (RCT_DEBUG && module == nil) {
UMLogError(@"Module for name `%@` has not been found.", moduleName);
return;
} else if (RCT_DEBUG && ![module conformsToProtocol:@protocol(UMEventEmitter)]) {
UMLogError(@"Module `%@` is not an UMEventEmitter, thus it cannot be subscribed to.", moduleName);
return;
}
id<UMEventEmitter> eventEmitter = (id<UMEventEmitter>)module;
// Per-module observing state
int newModuleListenersCount = [self moduleListenersCountFor:moduleName] - count;
if (newModuleListenersCount == 0) {
[eventEmitter stopObserving];
} else if (newModuleListenersCount < 0) {
UMLogError(@"Attempted to remove more `%@` listeners than added", moduleName);
newModuleListenersCount = 0;
}
_modulesListenersCounts[moduleName] = [NSNumber numberWithInt:newModuleListenersCount];
// Global observing state
if (_listenersCount - count < 0) {
UMLogError(@"Attempted to remove more proxied event emitter listeners than added");
_listenersCount = 0;
} else {
_listenersCount -= count;
}
if (_listenersCount == 0) {
[self stopObserving];
}
}
# pragma mark Utilities
- (int)moduleListenersCountFor:(NSString *)moduleName
{
NSNumber *moduleListenersCountNumber = _modulesListenersCounts[moduleName];
int moduleListenersCount = 0;
if (moduleListenersCountNumber != nil) {
moduleListenersCount = [moduleListenersCountNumber intValue];
}
return moduleListenersCount;
}
# pragma mark - UMModuleRegistryConsumer
- (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry
{
_umModuleRegistry = moduleRegistry;
}
@end