Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ios): compatible with non-ordered node operations (vue3 feature) #3966

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
89 changes: 45 additions & 44 deletions renderer/native/ios/renderer/HippyUIManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -91,60 +91,54 @@
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

/// Used to record the structural relationships of views
@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 +148,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 +781,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 +1001,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 +1030,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
Loading