Skip to content

Commit

Permalink
fix(ios): compatible with non-ordered node operations (vue3 feature)
Browse files Browse the repository at this point in the history
  • Loading branch information
wwwcg committed Jul 24, 2024
1 parent 390c338 commit 4a8a313
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 62 deletions.
6 changes: 2 additions & 4 deletions renderer/native/ios/renderer/HippyComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,8 @@ typedef void (^HippyDirectEventBlock)(NSDictionary *body);
- (void)removeHippySubview:(id<HippyComponent>)subview;

/// Move
/// - Parameters:
/// - subview: id
/// - atIndex: NSUInteger
- (void)moveHippySubview:(id<HippyComponent>)subview toIndex:(NSUInteger)atIndex;
/// - Parameter movedSubviewsIndexMap: IndexToSubView Map
- (void)moveHippySubviews:(NSDictionary<NSNumber *, id<HippyComponent>> *)movedSubviewsIndexMap;

/// Remove from superview
- (void)removeFromHippySuperview;
Expand Down
88 changes: 44 additions & 44 deletions renderer/native/ios/renderer/HippyUIManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -91,60 +91,53 @@
return viewName;
}

using HPViewBinding = std::map<int32_t, std::tuple<std::vector<int32_t>, std::vector<int32_t>>>;

constexpr char kVSyncKey[] = "frameupdate";

@interface NativeRenderViewsRelation : NSObject {
HPViewBinding _viewRelation;

#pragma mark - HippyViewsRelation

@interface HippyViewsRelation : NSObject {
std::map<int32_t, std::map<int32_t, int32_t>> _viewRelation;
}

/// Add one view to viewRelation
/// - Parameters:
/// - viewTag: self tag
/// - superviewTag: super tag
/// - index: final render index
- (void)addViewTag:(int32_t)viewTag forSuperViewTag:(int32_t)superviewTag atIndex:(int32_t)index;

- (void)enumerateViewsRelation:(void (^)(NSNumber *, NSArray<NSNumber *> *, NSArray<NSNumber *> *))block;

/// Clear
- (void)removeAllObjects;

@end

@implementation NativeRenderViewsRelation
@implementation HippyViewsRelation

- (void)addViewTag:(int32_t)viewTag forSuperViewTag:(int32_t)superviewTag atIndex:(int32_t)index {
if (superviewTag) {
auto &viewTuple = _viewRelation[superviewTag];
auto &subviewTagTuple = std::get<0>(viewTuple);
auto &subviewIndexTuple = std::get<1>(viewTuple);
subviewTagTuple.push_back(viewTag);
subviewIndexTuple.push_back(index);
}
}

- (void)enumerateViewsRelation:(void (^)(NSNumber *, NSArray<NSNumber *> *, NSArray<NSNumber *> *))block {
//using HPViewBinding = std::unordered_map<int32_t, std::tuple<std::vector<int32_t>, std::vector<int32_t>>>;
for (const auto &element : _viewRelation) {
NSNumber *superviewTag = @(element.first);
const auto &subviewTuple = element.second;
const auto &subviewTags = std::get<0>(subviewTuple);
NSMutableArray<NSNumber *> *subviewTagsArray = [NSMutableArray arrayWithCapacity:subviewTags.size()];
for (const auto &subviewTag : subviewTags) {
[subviewTagsArray addObject:@(subviewTag)];
}
const auto &subviewIndex = std::get<1>(subviewTuple);
NSMutableArray<NSNumber *> *subviewIndexArray = [NSMutableArray arrayWithCapacity:subviewIndex.size()];
for (const auto &subviewIndex : subviewIndex) {
[subviewIndexArray addObject:@(subviewIndex)];
}
block(superviewTag, [subviewTagsArray copy], [subviewIndexArray copy]);
auto &viewRelationPair = _viewRelation[superviewTag];
viewRelationPair[index] = viewTag;
}
}

- (void)enumerateViewsHierarchy:(void (^)(int32_t , const std::vector<int32_t> &, const std::vector<int32_t> &))block {
for (const auto &element : _viewRelation) {
int32_t tag = element.first;
const auto &subviewTuple = element.second;
const auto &subviewTags = std::get<0>(subviewTuple);
const auto &subviewIndex = std::get<1>(subviewTuple);
block(tag, subviewTags, subviewIndex);
for (const auto &viewRelationPair : _viewRelation) {
int32_t parentViewTag = viewRelationPair.first;
const auto& subviewRelations = viewRelationPair.second;

// Preallocate memory
std::vector<int32_t> subviewIndexes;
std::vector<int32_t> subviewTags;
subviewIndexes.reserve(subviewRelations.size());
subviewTags.reserve(subviewRelations.size());

// Store keys and values into separate vectors
for (const auto& subviewPair : subviewRelations) {
subviewIndexes.emplace_back(subviewPair.first);
subviewTags.emplace_back(subviewPair.second);
}
block(parentViewTag, subviewTags, subviewIndexes);
}
}

Expand All @@ -154,6 +147,9 @@ - (void)removeAllObjects {

@end


#pragma mark -

static void NativeRenderTraverseViewNodes(id<HippyComponent> view, void (^block)(id<HippyComponent>)) {
if (view.hippyTag != nil) {
block(view);
Expand Down Expand Up @@ -784,7 +780,7 @@ - (void)createRenderNodes:(std::vector<std::shared_ptr<DomNode>> &&)nodes
#endif
NSNumber *rootNodeTag = @(strongRootNode->GetId());
std::lock_guard<std::mutex> lock([self renderQueueLock]);
NativeRenderViewsRelation *manager = [[NativeRenderViewsRelation alloc] init];
HippyViewsRelation *manager = [[HippyViewsRelation alloc] init];
for (const std::shared_ptr<DomNode> &node : nodes) {
const auto& render_info = node->GetRenderInfo();
[manager addViewTag:render_info.id forSuperViewTag:render_info.pid atIndex:render_info.index];
Expand Down Expand Up @@ -1004,21 +1000,24 @@ - (void)renderMoveNodes:(std::vector<std::shared_ptr<hippy::DomNode>> &&)nodes
int32_t rootTag = strongRootNode->GetId();
std::lock_guard<std::mutex> lock([self renderQueueLock]);
HippyShadowView *parentObjectView = nil;
NSMutableDictionary<NSNumber *, HippyShadowView *> *movesMap = [NSMutableDictionary dictionaryWithCapacity:nodes.size()];
for (auto &node : nodes) {
int32_t index = node->GetRenderInfo().index;
int32_t componentTag = node->GetId();
HippyShadowView *objectView = [_shadowViewRegistry componentForTag:@(componentTag) onRootTag:@(rootTag)];
[objectView dirtyPropagation:NativeRenderUpdateLifecycleLayoutDirtied];
HippyAssert(!parentObjectView || parentObjectView == [objectView parent], @"parent not same!");
HippyShadowView *shadowView = [_shadowViewRegistry componentForTag:@(componentTag) onRootTag:@(rootTag)];
[shadowView dirtyPropagation:NativeRenderUpdateLifecycleLayoutDirtied];
HippyAssert(!parentObjectView || parentObjectView == [shadowView parent], @"parent not same!");
if (!parentObjectView) {
parentObjectView = (HippyShadowView *)[objectView parent];
parentObjectView = (HippyShadowView *)[shadowView parent];
}
[parentObjectView moveHippySubview:objectView toIndex:index];
[movesMap setObject:shadowView forKey:@(index)];
}
[parentObjectView moveHippySubviews:movesMap];
[parentObjectView didUpdateHippySubviews];
auto strongNodes = std::move(nodes);
[self addUIBlock:^(__unused HippyUIManager *uiManager, NSDictionary<NSNumber *,__kindof UIView *> *viewRegistry) {
UIView *superView = nil;
NSMutableDictionary<NSNumber *, UIView *> *moveViewsMap = [NSMutableDictionary dictionaryWithCapacity:strongNodes.size()];
for (auto node : strongNodes) {
int32_t index = node->GetRenderInfo().index;
int32_t componentTag = node->GetId();
Expand All @@ -1030,8 +1029,9 @@ - (void)renderMoveNodes:(std::vector<std::shared_ptr<hippy::DomNode>> &&)nodes
if (!superView) {
superView = (UIView *)[view parent];
}
[superView moveHippySubview:view toIndex:index];
[moveViewsMap setObject:view forKey:@(index)];
}
[superView moveHippySubviews:moveViewsMap];
[superView clearSortedSubviews];
[superView didUpdateHippySubviews];
}];
Expand Down
18 changes: 12 additions & 6 deletions renderer/native/ios/renderer/component/view/HippyShadowView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -195,13 +195,19 @@ - (void)insertHippySubview:(HippyShadowView *)subview atIndex:(NSUInteger)atInde
[self dirtyPropagation:NativeRenderUpdateLifecycleLayoutDirtied];
}

- (void)moveHippySubview:(id<HippyComponent>)subview toIndex:(NSUInteger)atIndex {
if (!subview) {
HippyAssert(subview != nil, @"subview should not be nil!");
return;
- (void)moveHippySubviews:(NSDictionary<NSNumber *,id<HippyComponent>> *)movedSubviewsIndexMap {
// First, remove
for (id<HippyComponent> subview in movedSubviewsIndexMap.allValues) {
[self removeHippySubview:subview];
}

// Second, place subview to its right place
// Since the inex here means the final index to place,
// it must be inserted from smallest to largest, otherwise it will be out of order.
NSArray *orderedIndexes = [[movedSubviewsIndexMap allKeys] sortedArrayUsingSelector:@selector(compare:)];
for (NSNumber *index in orderedIndexes) {
[self insertHippySubview:movedSubviewsIndexMap[index] atIndex:index.unsignedLongValue];
}
[self removeHippySubview:subview];
[self insertHippySubview:subview atIndex:atIndex];
}

- (void)removeHippySubview:(HippyShadowView *)subview {
Expand Down
17 changes: 12 additions & 5 deletions renderer/native/ios/renderer/component/view/UIView+Hippy.mm
Original file line number Diff line number Diff line change
Expand Up @@ -178,12 +178,19 @@ - (void)insertHippySubview:(UIView *)subview atIndex:(NSUInteger)atIndex {
subview.parent = self;
}

- (void)moveHippySubview:(UIView *)subview toIndex:(NSUInteger)atIndex {
if (nil == subview) {
return;
- (void)moveHippySubviews:(NSDictionary<NSNumber *,id<HippyComponent>> *)movedSubviewsIndexMap {
// First, remove
for (id<HippyComponent> subview in movedSubviewsIndexMap.allValues) {
[self removeHippySubview:subview];
}

// Second, place subview to its right place
// Since the inex here means the final index to place,
// it must be inserted from smallest to largest, otherwise it will be out of order.
NSArray *orderedIndexes = [[movedSubviewsIndexMap allKeys] sortedArrayUsingSelector:@selector(compare:)];
for (NSNumber *index in orderedIndexes) {
[self insertHippySubview:movedSubviewsIndexMap[index] atIndex:index.unsignedLongValue];
}
[self removeHippySubview:subview];
[self insertHippySubview:subview atIndex:atIndex];
}

- (void)removeHippySubview:(UIView *)subview {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,11 @@ - (void)removeHippySubview:(HippyShadowView *)subview {
[_itemChangeContext appendDeletedItem:subview];
}

- (void)moveHippySubview:(id<HippyComponent>)subview toIndex:(NSUInteger)atIndex {
[super moveHippySubview:subview toIndex:atIndex];
[_itemChangeContext appendMovedItem:subview];
- (void)moveHippySubviews:(NSDictionary<NSNumber *, id<HippyComponent>> *)movedSubviewsIndexMap {
[super moveHippySubviews:movedSubviewsIndexMap];
for (id<HippyComponent> subview in movedSubviewsIndexMap.allValues) {
[_itemChangeContext appendMovedItem:subview];
}
}

- (void)itemFrameChanged:(__kindof HippyShadowWaterfallItem *)item {
Expand Down

0 comments on commit 4a8a313

Please sign in to comment.