@@ -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