RCTGenericDelegateSplitter.mm 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #import "RCTGenericDelegateSplitter.h"
  8. @implementation RCTGenericDelegateSplitter {
  9. NSHashTable *_delegates;
  10. }
  11. #pragma mark - Public
  12. - (instancetype)initWithDelegateUpdateBlock:(void (^)(id _Nullable delegate))block
  13. {
  14. if (self = [super init]) {
  15. _delegateUpdateBlock = block;
  16. _delegates = [NSHashTable weakObjectsHashTable];
  17. }
  18. return self;
  19. }
  20. - (void)addDelegate:(id)delegate
  21. {
  22. [_delegates addObject:delegate];
  23. [self _updateDelegate];
  24. }
  25. - (void)removeDelegate:(id)delegate
  26. {
  27. [_delegates removeObject:delegate];
  28. [self _updateDelegate];
  29. }
  30. - (void)removeAllDelegates
  31. {
  32. [_delegates removeAllObjects];
  33. [self _updateDelegate];
  34. }
  35. #pragma mark - Private
  36. - (void)_updateDelegate
  37. {
  38. _delegateUpdateBlock(nil);
  39. if (_delegates.count == 0) {
  40. return;
  41. }
  42. _delegateUpdateBlock(_delegates.count == 1 ? [_delegates allObjects].firstObject : self);
  43. }
  44. #pragma mark - Fast Forwarding
  45. - (BOOL)respondsToSelector:(SEL)selector
  46. {
  47. for (id delegate in _delegates) {
  48. if ([delegate respondsToSelector:selector]) {
  49. return YES;
  50. }
  51. }
  52. return NO;
  53. }
  54. - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
  55. {
  56. for (id delegate in _delegates) {
  57. if ([delegate respondsToSelector:selector]) {
  58. return [delegate methodSignatureForSelector:selector];
  59. }
  60. }
  61. return nil;
  62. }
  63. - (void)forwardInvocation:(NSInvocation *)invocation
  64. {
  65. NSMutableArray *targets = [[NSMutableArray alloc] initWithCapacity:_delegates.count];
  66. for (id delegate in _delegates) {
  67. if ([delegate respondsToSelector:[invocation selector]]) {
  68. [targets addObject:delegate];
  69. }
  70. }
  71. for (id target in targets) {
  72. [invocation invokeWithTarget:target];
  73. }
  74. }
  75. @end