/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "RCTGenericDelegateSplitter.h" @implementation RCTGenericDelegateSplitter { NSHashTable *_delegates; } #pragma mark - Public - (instancetype)initWithDelegateUpdateBlock:(void (^)(id _Nullable delegate))block { if (self = [super init]) { _delegateUpdateBlock = block; _delegates = [NSHashTable weakObjectsHashTable]; } return self; } - (void)addDelegate:(id)delegate { [_delegates addObject:delegate]; [self _updateDelegate]; } - (void)removeDelegate:(id)delegate { [_delegates removeObject:delegate]; [self _updateDelegate]; } - (void)removeAllDelegates { [_delegates removeAllObjects]; [self _updateDelegate]; } #pragma mark - Private - (void)_updateDelegate { _delegateUpdateBlock(nil); if (_delegates.count == 0) { return; } _delegateUpdateBlock(_delegates.count == 1 ? [_delegates allObjects].firstObject : self); } #pragma mark - Fast Forwarding - (BOOL)respondsToSelector:(SEL)selector { for (id delegate in _delegates) { if ([delegate respondsToSelector:selector]) { return YES; } } return NO; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { for (id delegate in _delegates) { if ([delegate respondsToSelector:selector]) { return [delegate methodSignatureForSelector:selector]; } } return nil; } - (void)forwardInvocation:(NSInvocation *)invocation { NSMutableArray *targets = [[NSMutableArray alloc] initWithCapacity:_delegates.count]; for (id delegate in _delegates) { if ([delegate respondsToSelector:[invocation selector]]) { [targets addObject:delegate]; } } for (id target in targets) { [invocation invokeWithTarget:target]; } } @end