Skip to content

Commit 277ad44

Browse files
committed
refactor(ios): optimize segment view reconciliation by tracking remaining signatures for reuse
1 parent 80a52d3 commit 277ad44

1 file changed

Lines changed: 27 additions & 6 deletions

File tree

ios/utils/SegmentReconciler.m

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ @implementation ENRMSegmentReconciler
4040
}
4141
}];
4242

43+
NSMutableDictionary<NSNumber *, NSNumber *> *remainingNextSignatureCounts =
44+
[NSMutableDictionary dictionaryWithCapacity:renderedSegments.count];
45+
for (ENRMRenderedSegment *segment in renderedSegments) {
46+
NSNumber *signature = @(segment.signature);
47+
NSUInteger count = remainingNextSignatureCounts[signature].unsignedIntegerValue;
48+
remainingNextSignatureCounts[signature] = @(count + 1);
49+
}
50+
4351
NSMutableArray<RCTUIView *> *nextViews = [NSMutableArray arrayWithCapacity:renderedSegments.count];
4452
NSMutableArray<NSNumber *> *nextSignatures = [NSMutableArray arrayWithCapacity:renderedSegments.count];
4553
NSMutableSet<RCTUIView *> *reusedViews = [NSMutableSet setWithCapacity:sourceViews.count];
@@ -50,11 +58,16 @@ @implementation ENRMSegmentReconciler
5058
RCTUIView *view = nil;
5159
NSNumber *nextSignature = @(segment.signature);
5260

53-
// 1. Positional match: same index, same kind.
54-
if (existingView && ![reusedViews containsObject:existingView] && matchesKind(existingView, segment)) {
55-
if (![existingSignature isEqual:nextSignature]) {
56-
updateView(existingView, segment);
57-
}
61+
NSUInteger remainingNextSignatureCount = remainingNextSignatureCounts[nextSignature].unsignedIntegerValue;
62+
if (remainingNextSignatureCount > 1) {
63+
remainingNextSignatureCounts[nextSignature] = @(remainingNextSignatureCount - 1);
64+
} else {
65+
[remainingNextSignatureCounts removeObjectForKey:nextSignature];
66+
}
67+
68+
// 1. Exact positional match: the same view still represents the same segment.
69+
if (existingView && ![reusedViews containsObject:existingView] && matchesKind(existingView, segment) &&
70+
[existingSignature isEqual:nextSignature]) {
5871
view = existingView;
5972
}
6073

@@ -72,7 +85,15 @@ @implementation ENRMSegmentReconciler
7285
}
7386
}
7487

75-
// 3. No reusable view found — create a new one.
88+
// 3. Same-kind positional update. If this old signature appears later in
89+
// the new list, leave the view available for that exact reuse instead.
90+
if (!view && existingView && ![reusedViews containsObject:existingView] && matchesKind(existingView, segment) &&
91+
(existingSignature == nil || remainingNextSignatureCounts[existingSignature].unsignedIntegerValue == 0)) {
92+
updateView(existingView, segment);
93+
view = existingView;
94+
}
95+
96+
// 4. No reusable view found — create a new one.
7697
if (!view) {
7798
view = createView(segment);
7899
attachView(view);

0 commit comments

Comments
 (0)