Skip to content

Commit

Permalink
fix(ios): fix component reference issue on old system versions
Browse files Browse the repository at this point in the history
  • Loading branch information
wwwcg authored and hippy-actions[bot] committed Dec 22, 2023
1 parent ebbb3f7 commit 4d904b0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 37 deletions.
24 changes: 20 additions & 4 deletions renderer/native/ios/renderer/HippyComponentMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,31 @@ class RootNode;

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSUInteger, HippyComponentReferenceType) {
HippyComponentReferenceTypeStrong,
HippyComponentReferenceTypeWeak,
};

@interface HippyComponentMap : NSObject

/// Whether all recorded elements are strongly referenced,
///
/// Attention, Attention, Attention:
/// All UI views are weakly referenced!
/// All Shadowviews are strongly referenced!
@property (nonatomic, assign, readonly) BOOL isStrongHoldAllComponents;

/// Whether access is required from the main thread
@property(nonatomic, assign) BOOL requireInMainThread;

/// Init Method
- (instancetype)initWithComponentsReferencedType:(HippyComponentReferenceType)type;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

- (void)addRootComponent:(id<HippyComponent>)component
rootNode:(std::weak_ptr<hippy::RootNode>)rootNode
forTag:(NSNumber *)tag
strongHoldComponents:(BOOL)shouldStrongHoldAllComponents;

forTag:(NSNumber *)tag;

- (void)removeRootComponentWithTag:(NSNumber *)tag;

Expand All @@ -62,7 +78,7 @@ NS_ASSUME_NONNULL_BEGIN

- (void)removeComponentByComponentTag:(NSNumber *)componentTag onRootTag:(NSNumber *)rootTag;

- (NSMutableDictionary<NSNumber *, __kindof id<HippyComponent>> *)componentsForRootTag:(NSNumber *)tag;
- (NSDictionary<NSNumber *, __kindof id<HippyComponent>> *)componentsForRootTag:(NSNumber *)tag;

- (__kindof id<HippyComponent>)componentForTag:(NSNumber *)componentTag
onRootTag:(NSNumber *)tag;
Expand Down
16 changes: 10 additions & 6 deletions renderer/native/ios/renderer/HippyComponentMap.mm
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ @interface HippyComponentMap () {

@implementation HippyComponentMap

- (instancetype)init {
- (instancetype)initWithComponentsReferencedType:(HippyComponentReferenceType)type {
self = [super init];
if (self) {
_isStrongHoldAllComponents = (HippyComponentReferenceTypeStrong == type);
_rootComponentsMap = [NSMapTable strongToWeakObjectsMapTable];
_componentsMap = [NSMutableDictionary dictionary];
_rootNodesMap.reserve(8);
Expand All @@ -52,13 +53,12 @@ - (BOOL)threadCheck {

- (void)addRootComponent:(id<HippyComponent>)component
rootNode:(std::weak_ptr<hippy::RootNode>)rootNode
forTag:(NSNumber *)tag
strongHoldComponents:(BOOL)shouldStrongHoldAllComponents {
forTag:(NSNumber *)tag {
NSAssert(component && tag, @"component &&tag must not be null in method %@", NSStringFromSelector(_cmd));
NSAssert([self threadCheck], @"%@ method needs run in main thread", NSStringFromSelector(_cmd));
if (component && tag && ![_componentsMap objectForKey:tag]) {
id dic = nil;
if (shouldStrongHoldAllComponents) {
if (_isStrongHoldAllComponents) {
dic = [NSMutableDictionary dictionary];
} else {
dic = [NSMapTable strongToWeakObjectsMapTable];
Expand Down Expand Up @@ -128,12 +128,16 @@ - (void)removeComponentByComponentTag:(NSNumber *)componentTag onRootTag:(NSNumb
}
}

- (NSMutableDictionary<NSNumber * ,__kindof id<HippyComponent>> *)componentsForRootTag:(NSNumber *)tag {
- (NSDictionary<NSNumber * ,__kindof id<HippyComponent>> *)componentsForRootTag:(NSNumber *)tag {
NSAssert(tag, @"tag must not be null in method %@", NSStringFromSelector(_cmd));
NSAssert([self threadCheck], @"%@ method needs run in main thread", NSStringFromSelector(_cmd));
if (tag) {
id map = [_componentsMap objectForKey:tag];
return map;
if (_isStrongHoldAllComponents) {
return map;
} else {
return ((NSMapTable *)map).dictionaryRepresentation;
}
}
return nil;
}
Expand Down
47 changes: 20 additions & 27 deletions renderer/native/ios/renderer/HippyUIManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ - (void)dealloc {
}

- (void)initContext {
_shadowViewRegistry = [[HippyComponentMap alloc] init];
_viewRegistry = [[HippyComponentMap alloc] init];
_shadowViewRegistry = [[HippyComponentMap alloc] initWithComponentsReferencedType:HippyComponentReferenceTypeStrong];
_viewRegistry = [[HippyComponentMap alloc] initWithComponentsReferencedType:HippyComponentReferenceTypeWeak];
_viewRegistry.requireInMainThread = YES;
_pendingUIBlocks = [NSMutableArray new];
_componentTransactionListeners = [NSHashTable weakObjectsHashTable];
Expand Down Expand Up @@ -263,20 +263,6 @@ - (void)domNodeForComponentTag:(int32_t)componentTag
}
}

- (HippyComponentMap *)renderObjectRegistry {
if (!_shadowViewRegistry) {
_shadowViewRegistry = [[HippyComponentMap alloc] init];
}
return _shadowViewRegistry;
}

- (HippyComponentMap *)viewRegistry {
if (!_viewRegistry) {
_viewRegistry = [[HippyComponentMap alloc] init];
}
return _viewRegistry;
}

- (UIView *)viewForHippyTag:(NSNumber *)hippyTag onRootTag:(NSNumber *)rootTag {
AssertMainQueue();
return [_viewRegistry componentForTag:hippyTag onRootTag:rootTag];
Expand Down Expand Up @@ -323,7 +309,7 @@ - (void)registerRootView:(UIView *)rootView asRootNode:(std::weak_ptr<RootNode>)
NSAssert(![_viewRegistry containRootComponentWithTag:componentTag], @"RootView Tag already exists. Added %@ twice", componentTag);
#endif
// Register view
[_viewRegistry addRootComponent:rootView rootNode:rootNode forTag:componentTag strongHoldComponents:NO];
[_viewRegistry addRootComponent:rootView rootNode:rootNode forTag:componentTag];
[rootView addObserver:self forKeyPath:@"frame" options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:NULL];
rootView.renderManager = [self renderManager];
Expand All @@ -347,7 +333,7 @@ - (void)registerRootView:(UIView *)rootView asRootNode:(std::weak_ptr<RootNode>)
renderObject.viewName = rootViewClassName;
renderObject.rootNode = rootNode;
renderObject.domNode = rootNode;
[strongSelf->_shadowViewRegistry addRootComponent:renderObject rootNode:rootNode forTag:componentTag strongHoldComponents:YES];
[strongSelf->_shadowViewRegistry addRootComponent:renderObject rootNode:rootNode forTag:componentTag];
NSDictionary *userInfo = @{ NativeRenderUIManagerRootViewTagKey: componentTag,
NativeRenderUIManagerKey: strongSelf};
[[NSNotificationCenter defaultCenter] postNotificationName:NativeRenderUIManagerDidRegisterRootViewNotification
Expand Down Expand Up @@ -462,14 +448,15 @@ - (void)setFrame:(CGRect)frame forRootView:(UIView *)view {
*/
- (void)purgeChildren:(NSArray<id<HippyComponent>> *)children
onRootTag:(NSNumber *)rootTag
fromRegistry:(NSMutableDictionary<NSNumber *, __kindof id<HippyComponent>> *)registry {
fromRegistry:(HippyComponentMap *)registryMap {
NSDictionary *currentRegistry = [registryMap componentsForRootTag:rootTag];
for (id<HippyComponent> child in children) {
NativeRenderTraverseViewNodes(registry[child.hippyTag], ^(id<HippyComponent> subview) {
NativeRenderTraverseViewNodes(currentRegistry[child.hippyTag], ^(id<HippyComponent> subview) {
NSAssert(![subview isHippyRootView], @"Root views should not be unregistered");
if ([subview respondsToSelector:@selector(invalidate)]) {
[subview performSelector:@selector(invalidate)];
}
[registry removeObjectForKey:subview.hippyTag];
[registryMap removeComponent:subview forRootTag:rootTag];
});
}
}
Expand Down Expand Up @@ -588,8 +575,10 @@ - (UIView *)createViewRecursiveFromRenderObjectWithNOLock:(HippyShadowView *)sha
NSMutableSet<NativeRenderApplierBlock> *applierBlocks = [NSMutableSet set];
[shadowView amendLayoutBeforeMount:applierBlocks];
if (applierBlocks.count) {
NSDictionary<NSNumber *, UIView *> *viewRegistry = [self.viewRegistry componentsForRootTag:shadowView.rootTag];
for (NativeRenderApplierBlock block in applierBlocks) {
// Note: viewRegistry may be modified in the block, and it may be stored internally as NSMapTable
// so to ensure that it is up-to-date, it can only be retrieved each time.
NSDictionary<NSNumber *, UIView *> *viewRegistry = [self.viewRegistry componentsForRootTag:shadowView.rootTag];
block(viewRegistry, view);
}
}
Expand Down Expand Up @@ -739,9 +728,11 @@ - (void)flushUIBlocksOnRootNode:(std::weak_ptr<RootNode>)rootNode {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
TDF_PERF_LOG("flushUIBlocksOnRootNode on main thread(random id:%u)",rand);
NSDictionary<NSNumber *, UIView *> *viewReg = [strongSelf.viewRegistry componentsForRootTag:@(rootTag)];
for (HippyViewManagerUIBlock block in previousPendingUIBlocks) {
@try {
// Note: viewRegistry may be modified in the block, and it may be stored internally as NSMapTable
// so to ensure that it is up-to-date, it can only be retrieved each time.
NSDictionary* viewReg = [strongSelf.viewRegistry componentsForRootTag:@(rootTag)];
block(strongSelf, viewReg);
} @catch (NSException *exception) {
HippyLogError(@"Exception thrown while executing UI block: %@", exception);
Expand Down Expand Up @@ -843,6 +834,9 @@ - (void)createRenderNodes:(std::vector<std::shared_ptr<DomNode>> &&)nodes
}];
}
}];
[self addUIBlock:^(HippyUIManager *uiManager, NSDictionary<NSNumber *,__kindof UIView *> *viewRegistry) {
HippyLogInfo(@"Created views: %lu, full registry: %lu", (unsigned long)tempCreatedViews.count, viewRegistry.count);
}];
}
- (void)updateRenderNodes:(std::vector<std::shared_ptr<DomNode>>&&)nodes
Expand Down Expand Up @@ -891,15 +885,15 @@ - (void)deleteRenderNodesIds:(std::vector<std::shared_ptr<hippy::DomNode>> &&)no
#endif
std::lock_guard<std::mutex> lock([self renderQueueLock]);
NSNumber *rootTag = @(strongRootNode->GetId());
NSMutableDictionary *currentRegistry = [_shadowViewRegistry componentsForRootTag:rootTag];
NSDictionary *currentRegistry = [_shadowViewRegistry componentsForRootTag:rootTag];
for (auto dom_node : nodes) {
int32_t tag = dom_node->GetRenderInfo().id;
HippyShadowView *renderObject = [currentRegistry objectForKey:@(tag)];
[renderObject dirtyPropagation:NativeRenderUpdateLifecycleLayoutDirtied];
if (renderObject) {
[renderObject removeFromHippySuperview];
[self purgeChildren:@[renderObject] onRootTag:rootTag fromRegistry:currentRegistry];
[self purgeChildren:@[renderObject] onRootTag:rootTag fromRegistry:_shadowViewRegistry];
}
}
__weak HippyUIManager *weakSelf = self;
Expand All @@ -924,8 +918,7 @@ - (void)deleteRenderNodesIds:(std::vector<std::shared_ptr<hippy::DomNode>> &&)no
[view removeFromHippySuperview];
[views addObject:view];
}
NSMutableDictionary *currentViewRegistry = [strongSelf.viewRegistry componentsForRootTag:rootTag];
[strongSelf purgeChildren:views onRootTag:rootTag fromRegistry:currentViewRegistry];
[strongSelf purgeChildren:views onRootTag:rootTag fromRegistry:strongSelf.viewRegistry];
for (UIView *view in parentViews) {
[view clearSortedSubviews];
[view didUpdateHippySubviews];
Expand Down

0 comments on commit 4d904b0

Please sign in to comment.