1// Copyright 2018-present 650 Industries. All rights reserved.
2
3#import <objc/runtime.h>
4
5#import <ABI47_0_0ExpoModulesCore/ABI47_0_0EXViewManagerAdapterClassesRegistry.h>
6#import <ABI47_0_0ExpoModulesCore/ABI47_0_0EXViewManagerAdapter.h>
7
8static const NSString *viewManagerAdapterModuleNamePrefix = @"ViewManagerAdapter_";
9
10static IMP directEventBlockImplementation = nil;
11static dispatch_once_t directEventBlockImplementationOnceToken;
12
13@interface ABI47_0_0EXViewManagerAdapterClassesRegistry ()
14
15@property (nonatomic, strong) NSMutableDictionary<Class, Class> *viewManagerAdaptersClasses;
16
17@end
18
19@implementation ABI47_0_0EXViewManagerAdapterClassesRegistry
20
21- (instancetype)init
22{
23  if (self = [super init]) {
24    _viewManagerAdaptersClasses = [NSMutableDictionary dictionary];
25  }
26  return self;
27}
28
29- (Class)viewManagerAdapterClassForViewManager:(ABI47_0_0EXViewManager *)viewManager
30{
31  Class viewManagerClass = [viewManager class];
32  if (_viewManagerAdaptersClasses[viewManagerClass] == nil) {
33    _viewManagerAdaptersClasses[(id <NSCopying>)viewManagerClass] = [self.class createViewManagerAdapterClassForViewManager:viewManager];
34  }
35  return _viewManagerAdaptersClasses[viewManagerClass];
36}
37
38+ (Class)createViewManagerAdapterClassForViewManager:(ABI47_0_0EXViewManager *)viewManager
39{
40  const char *viewManagerClassName = [[viewManagerAdapterModuleNamePrefix stringByAppendingString:[viewManager viewName]] UTF8String];
41  Class viewManagerAdapterClass = objc_allocateClassPair([ABI47_0_0EXViewManagerAdapter class], viewManagerClassName, 0);
42  Class metaClass = object_getClass(viewManagerAdapterClass);
43
44  [self _ensureDirectEventBlockImplementationIsPresent];
45
46  for (NSString *eventName in [viewManager supportedEvents]) {
47    class_addMethod(metaClass, NSSelectorFromString([@"propConfig_" stringByAppendingString:eventName]), directEventBlockImplementation, "@@:");
48  }
49
50  IMP viewManagerImp = imp_implementationWithBlock(^{
51    return viewManager;
52  });
53  class_addMethod(viewManagerAdapterClass, NSSelectorFromString(@"viewManager"), viewManagerImp, "@@:");
54
55  return viewManagerAdapterClass;
56}
57
58+ (void)_ensureDirectEventBlockImplementationIsPresent
59{
60  dispatch_once(&directEventBlockImplementationOnceToken, ^{
61    directEventBlockImplementation = imp_implementationWithBlock(^{
62      return @[@"ABI47_0_0RCTDirectEventBlock"];
63    });
64  });
65}
66
67@end
68