RCTEventEmitter.m 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 "RCTEventEmitter.h"
  8. #import "RCTAssert.h"
  9. #import "RCTLog.h"
  10. #import "RCTUtils.h"
  11. @implementation RCTEventEmitter {
  12. NSInteger _listenerCount;
  13. }
  14. @synthesize invokeJS = _invokeJS;
  15. + (NSString *)moduleName
  16. {
  17. return @"";
  18. }
  19. + (void)initialize
  20. {
  21. [super initialize];
  22. if (self != [RCTEventEmitter class]) {
  23. RCTAssert(
  24. RCTClassOverridesInstanceMethod(self, @selector(supportedEvents)),
  25. @"You must override the `supportedEvents` method of %@",
  26. self);
  27. }
  28. }
  29. - (NSArray<NSString *> *)supportedEvents
  30. {
  31. return nil;
  32. }
  33. - (void)sendEventWithName:(NSString *)eventName body:(id)body
  34. {
  35. RCTAssert(
  36. _bridge != nil || _invokeJS != nil,
  37. @"Error when sending event: %@ with body: %@. "
  38. "Bridge is not set. This is probably because you've "
  39. "explicitly synthesized the bridge in %@, even though it's inherited "
  40. "from RCTEventEmitter.",
  41. eventName,
  42. body,
  43. [self class]);
  44. if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
  45. RCTLogError(
  46. @"`%@` is not a supported event type for %@. Supported events are: `%@`",
  47. eventName,
  48. [self class],
  49. [[self supportedEvents] componentsJoinedByString:@"`, `"]);
  50. }
  51. if (_listenerCount > 0 && _bridge) {
  52. [_bridge enqueueJSCall:@"RCTDeviceEventEmitter"
  53. method:@"emit"
  54. args:body ? @[ eventName, body ] : @[ eventName ]
  55. completion:NULL];
  56. } else if (_listenerCount > 0 && _invokeJS) {
  57. _invokeJS(@"RCTDeviceEventEmitter", @"emit", body ? @[ eventName, body ] : @[ eventName ]);
  58. } else {
  59. RCTLogWarn(@"Sending `%@` with no listeners registered.", eventName);
  60. }
  61. }
  62. - (void)startObserving
  63. {
  64. // Does nothing
  65. }
  66. - (void)stopObserving
  67. {
  68. // Does nothing
  69. }
  70. - (void)dealloc
  71. {
  72. if (_listenerCount > 0) {
  73. [self stopObserving];
  74. }
  75. }
  76. RCT_EXPORT_METHOD(addListener : (NSString *)eventName)
  77. {
  78. if (RCT_DEBUG && ![[self supportedEvents] containsObject:eventName]) {
  79. RCTLogError(
  80. @"`%@` is not a supported event type for %@. Supported events are: `%@`",
  81. eventName,
  82. [self class],
  83. [[self supportedEvents] componentsJoinedByString:@"`, `"]);
  84. }
  85. _listenerCount++;
  86. if (_listenerCount == 1) {
  87. [self startObserving];
  88. }
  89. }
  90. RCT_EXPORT_METHOD(removeListeners : (double)count)
  91. {
  92. int currentCount = (int)count;
  93. if (RCT_DEBUG && currentCount > _listenerCount) {
  94. RCTLogError(@"Attempted to remove more %@ listeners than added", [self class]);
  95. }
  96. _listenerCount = MAX(_listenerCount - currentCount, 0);
  97. if (_listenerCount == 0) {
  98. [self stopObserving];
  99. }
  100. }
  101. @end