RCTComponentViewFactory.mm 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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 "RCTComponentViewFactory.h"
  8. #import <React/RCTAssert.h>
  9. #import <React/RCTConversions.h>
  10. #import <better/map.h>
  11. #import <better/mutex.h>
  12. #import <react/core/ReactPrimitives.h>
  13. #import <react/uimanager/ComponentDescriptorProviderRegistry.h>
  14. #ifdef RN_DISABLE_OSS_PLUGIN_HEADER
  15. #import <RCTFabricComponentPlugin/RCTFabricPluginProvider.h>
  16. #else
  17. #import "RCTFabricComponentsPlugins.h"
  18. #endif
  19. #import "RCTComponentViewClassDescriptor.h"
  20. #import "RCTFabricComponentsPlugins.h"
  21. #import "RCTImageComponentView.h"
  22. #import "RCTLegacyViewManagerInteropComponentView.h"
  23. #import "RCTMountingTransactionObserving.h"
  24. #import "RCTParagraphComponentView.h"
  25. #import "RCTRootComponentView.h"
  26. #import "RCTTextInputComponentView.h"
  27. #import "RCTUnimplementedViewComponentView.h"
  28. #import "RCTViewComponentView.h"
  29. #import <objc/runtime.h>
  30. using namespace facebook::react;
  31. static Class<RCTComponentViewProtocol> RCTComponentViewClassWithName(const char *componentName)
  32. {
  33. return RCTFabricComponentsProvider(componentName);
  34. }
  35. @implementation RCTComponentViewFactory {
  36. better::map<ComponentHandle, RCTComponentViewClassDescriptor> _componentViewClasses;
  37. ComponentDescriptorProviderRegistry _providerRegistry;
  38. better::shared_mutex _mutex;
  39. }
  40. + (RCTComponentViewFactory *)standardComponentViewFactory
  41. {
  42. RCTComponentViewFactory *componentViewFactory = [[RCTComponentViewFactory alloc] init];
  43. [componentViewFactory registerComponentViewClass:[RCTRootComponentView class]];
  44. [componentViewFactory registerComponentViewClass:[RCTViewComponentView class]];
  45. [componentViewFactory registerComponentViewClass:[RCTParagraphComponentView class]];
  46. [componentViewFactory registerComponentViewClass:[RCTTextInputComponentView class]];
  47. Class<RCTComponentViewProtocol> imageClass = RCTComponentViewClassWithName("Image");
  48. [componentViewFactory registerComponentViewClass:imageClass];
  49. auto providerRegistry = &componentViewFactory->_providerRegistry;
  50. providerRegistry->setComponentDescriptorProviderRequest(
  51. [providerRegistry, componentViewFactory](ComponentName requestedComponentName) {
  52. // Fallback 1: Call provider function for component view class.
  53. Class<RCTComponentViewProtocol> klass = RCTComponentViewClassWithName(requestedComponentName);
  54. if (klass) {
  55. [componentViewFactory registerComponentViewClass:klass];
  56. return;
  57. }
  58. // Fallback 2: Try to use Paper Interop.
  59. if ([RCTLegacyViewManagerInteropComponentView isSupported:RCTNSStringFromString(requestedComponentName)]) {
  60. auto flavor = std::make_shared<std::string const>(requestedComponentName);
  61. auto componentName = ComponentName{flavor->c_str()};
  62. auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
  63. auto constructor = [RCTLegacyViewManagerInteropComponentView componentDescriptorProvider].constructor;
  64. providerRegistry->add(ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor});
  65. componentViewFactory->_componentViewClasses[componentHandle] = [componentViewFactory
  66. _componentViewClassDescriptorFromClass:[RCTLegacyViewManagerInteropComponentView class]];
  67. return;
  68. }
  69. // Fallback 3: Finally use <UnimplementedView>.
  70. auto flavor = std::make_shared<std::string const>(requestedComponentName);
  71. auto componentName = ComponentName{flavor->c_str()};
  72. auto componentHandle = reinterpret_cast<ComponentHandle>(componentName);
  73. auto constructor = [RCTUnimplementedViewComponentView componentDescriptorProvider].constructor;
  74. providerRegistry->add(ComponentDescriptorProvider{componentHandle, componentName, flavor, constructor});
  75. componentViewFactory->_componentViewClasses[componentHandle] =
  76. [componentViewFactory _componentViewClassDescriptorFromClass:[RCTUnimplementedViewComponentView class]];
  77. });
  78. return componentViewFactory;
  79. }
  80. - (RCTComponentViewClassDescriptor)_componentViewClassDescriptorFromClass:(Class<RCTComponentViewProtocol>)viewClass
  81. {
  82. #pragma clang diagnostic push
  83. #pragma clang diagnostic ignored "-Wundeclared-selector"
  84. return RCTComponentViewClassDescriptor
  85. {
  86. .viewClass = viewClass,
  87. .observesMountingTransactionWillMount =
  88. (bool)class_respondsToSelector(viewClass, @selector(mountingTransactionWillMountWithMetadata:)),
  89. .observesMountingTransactionDidMount =
  90. (bool)class_respondsToSelector(viewClass, @selector(mountingTransactionDidMountWithMetadata:)),
  91. };
  92. #pragma clang diagnostic pop
  93. }
  94. - (void)registerComponentViewClass:(Class<RCTComponentViewProtocol>)componentViewClass
  95. {
  96. std::unique_lock<better::shared_mutex> lock(_mutex);
  97. auto componentDescriptorProvider = [componentViewClass componentDescriptorProvider];
  98. _componentViewClasses[componentDescriptorProvider.handle] =
  99. [self _componentViewClassDescriptorFromClass:componentViewClass];
  100. _providerRegistry.add(componentDescriptorProvider);
  101. auto supplementalComponentDescriptorProviders = [componentViewClass supplementalComponentDescriptorProviders];
  102. for (const auto &provider : supplementalComponentDescriptorProviders) {
  103. _providerRegistry.add(provider);
  104. }
  105. }
  106. - (RCTComponentViewDescriptor)createComponentViewWithComponentHandle:(facebook::react::ComponentHandle)componentHandle
  107. {
  108. RCTAssertMainQueue();
  109. std::shared_lock<better::shared_mutex> lock(_mutex);
  110. auto iterator = _componentViewClasses.find(componentHandle);
  111. RCTAssert(
  112. iterator != _componentViewClasses.end(),
  113. @"ComponentView with componentHandle `%lli` (`%s`) not found.",
  114. componentHandle,
  115. (char *)componentHandle);
  116. auto componentViewClassDescriptor = iterator->second;
  117. Class viewClass = componentViewClassDescriptor.viewClass;
  118. return RCTComponentViewDescriptor{
  119. .view = [[viewClass alloc] init],
  120. .observesMountingTransactionWillMount = componentViewClassDescriptor.observesMountingTransactionWillMount,
  121. .observesMountingTransactionDidMount = componentViewClassDescriptor.observesMountingTransactionDidMount,
  122. };
  123. }
  124. - (facebook::react::ComponentDescriptorRegistry::Shared)createComponentDescriptorRegistryWithParameters:
  125. (facebook::react::ComponentDescriptorParameters)parameters
  126. {
  127. std::shared_lock<better::shared_mutex> lock(_mutex);
  128. return _providerRegistry.createComponentDescriptorRegistry(parameters);
  129. }
  130. @end