in RenderCore/View/ComponentViewManager.mm [185:230]
void ViewReusePoolMap::reset(UIView *container, CK::Component::MountAnalyticsContext *mountAnalyticsContext) noexcept
{
for (auto &it : dictionary) {
it.second.reset(mountAnalyticsContext);
}
// Now we need to ensure that the ordering of container.subviews matches vendedViews.
NSMutableArray *subviews = [[container subviews] mutableCopy];
std::vector<UIView *>::const_iterator nextVendedViewIt = vendedViews.cbegin();
// Can't use NSFastEnumeration since we mutate subviews during enumeration.
for (NSUInteger i = 0; i < [subviews count]; i++) {
UIView *subview = subviews[i];
// We use linear search here. We could create a std::unordered_set of vended views, but given the typical size of
// the list of vended views, I guessed a linear search would probably be faster considering constant factors.
const auto &vendedViewIt = std::find(nextVendedViewIt, vendedViews.cend(), subview);
if (vendedViewIt == vendedViews.cend()) {
// Ignore subviews not created by components infra, or that were not vended during this pass (they are hidden).
continue;
}
if (vendedViewIt != nextVendedViewIt) {
NSUInteger swapIndex = [subviews indexOfObjectIdenticalTo:*nextVendedViewIt];
// This check can cause some z-ordering issue if views vended by the framework are manipulated outside of the framework,
if (swapIndex != NSNotFound) {
// This naive algorithm does not do the minimal number of swaps. But it's simple, and swaps should be relatively
// rare in any case, so let's go with it.
[subviews exchangeObjectAtIndex:i withObjectAtIndex:swapIndex];
[container exchangeSubviewAtIndex:i withSubviewAtIndex:swapIndex];
}
RCCAssertWithCategory(swapIndex != NSNotFound,
[CKMountedObjectForView(*nextVendedViewIt) class],
@"Expected to find subview %@ (mounted object: %@) in %@ (mounted object: %@)",
[*nextVendedViewIt class],
[CKMountedObjectForView(*nextVendedViewIt) class],
[container class],
[CKMountedObjectForView(container) class]);
}
++nextVendedViewIt;
}
vendedViews.clear();
}