@@ -50,6 +50,14 @@ static void RCTTraverseViewNodes(id<RCTComponent> view, void (^block)(id<RCTComp
5050 }
5151}
5252
53+ static NSString *RCTNativeIDRegistryKey (NSString *nativeID, NSNumber *rootTag)
54+ {
55+ if (!nativeID || !rootTag) {
56+ return @" " ;
57+ }
58+ return [NSString stringWithFormat: @" %@ -%@ " , rootTag, nativeID];
59+ }
60+
5361NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification = @" RCTUIManagerWillUpdateViewsDueToContentSizeMultiplierChangeNotification" ;
5462
5563@implementation RCTUIManager
@@ -63,6 +71,7 @@ @implementation RCTUIManager
6371
6472 NSMutableDictionary <NSNumber *, RCTShadowView *> *_shadowViewRegistry; // RCT thread only
6573 NSMutableDictionary <NSNumber *, UIView *> *_viewRegistry; // Main thread only
74+ NSMapTable <NSString *, UIView *> *_nativeIDRegistry; // Main thread only
6675
6776 NSMapTable <RCTShadowView *, NSArray <NSString *> *> *_shadowViewsWithUpdatedProps; // UIManager queue only.
6877 NSHashTable <RCTShadowView *> *_shadowViewsWithUpdatedChildren; // UIManager queue only.
@@ -106,6 +115,7 @@ - (void)invalidate
106115 self->_rootViewTags = nil ;
107116 self->_shadowViewRegistry = nil ;
108117 self->_viewRegistry = nil ;
118+ self->_nativeIDRegistry = nil ;
109119 self->_bridge = nil ;
110120
111121 [[NSNotificationCenter defaultCenter ] removeObserver: self ];
@@ -131,13 +141,23 @@ - (void)invalidate
131141 return _viewRegistry;
132142}
133143
144+ - (NSMapTable *)nativeIDRegistry
145+ {
146+ // Should be called on main queue
147+ if (!_nativeIDRegistry) {
148+ _nativeIDRegistry = [NSMapTable strongToWeakObjectsMapTable ];
149+ }
150+ return _nativeIDRegistry;
151+ }
152+
134153- (void )setBridge : (RCTBridge *)bridge
135154{
136155 RCTAssert (_bridge == nil , @" Should not re-use same UIManager instance" );
137156 _bridge = bridge;
138157
139158 _shadowViewRegistry = [NSMutableDictionary new ];
140159 _viewRegistry = [NSMutableDictionary new ];
160+ _nativeIDRegistry = [NSMapTable strongToWeakObjectsMapTable ];
141161
142162 _shadowViewsWithUpdatedProps = [NSMapTable weakToStrongObjectsMapTable ];
143163 _shadowViewsWithUpdatedChildren = [NSHashTable weakObjectsHashTable ];
@@ -366,31 +386,27 @@ - (void)setLocalData:(NSObject *)localData forView:(UIView *)view
366386 } forTag: view.reactTag];
367387}
368388
369- /* *
370- * TODO(yuwang): implement the nativeID functionality in a more efficient way
371- * instead of searching the whole view tree
372- */
373389- (UIView *)viewForNativeID : (NSString *)nativeID withRootTag : (NSNumber *)rootTag
374390{
375391 RCTAssertMainQueue ();
376- UIView *view = [self viewForReactTag: rootTag];
377- return [self _lookupViewForNativeID: nativeID inView: view];
392+ if (!nativeID || !rootTag) {
393+ return nil ;
394+ }
395+ return [_nativeIDRegistry objectForKey: RCTNativeIDRegistryKey (nativeID, rootTag)];
378396}
379397
380- - (UIView *) _lookupViewForNativeID : (NSString *)nativeID inView : (UIView *)view
398+ - (void ) setNativeID : (NSString *)nativeID forView : (UIView *)view
381399{
382400 RCTAssertMainQueue ();
383- if (view != nil && [ nativeID isEqualToString: view.nativeID] ) {
384- return view ;
401+ if (! nativeID) {
402+ return ;
385403 }
386-
387- for (UIView *subview in view.subviews ) {
388- UIView *targetView = [self _lookupViewForNativeID: nativeID inView: subview];
389- if (targetView != nil ) {
390- return targetView;
404+ __weak RCTUIManager *weakSelf = self;
405+ [self rootViewForReactTag: view.reactTag withCompletion: ^(UIView *rootView) {
406+ if (rootView) {
407+ [weakSelf.nativeIDRegistry setObject: view forKey: RCTNativeIDRegistryKey (nativeID, rootView.reactTag)];
391408 }
392- }
393- return nil ;
409+ }];
394410}
395411
396412- (void )setSize : (CGSize)size forView : (UIView *)view
0 commit comments