in ComponentKit/Core/CKComponentAttachController.mm [62:103]
void CKComponentAttachControllerAttachComponentRootLayout(
CKComponentAttachController *const self,
const CKComponentAttachControllerAttachComponentRootLayoutParams ¶ms)
{
RCCAssertMainThread();
if (self == nil) {
RCCAssert(self, @"Impossible to attach a component layout to a nil attachController");
return;
}
const auto view = params.view;
UIView *currentlyAttachedView = self->_scopeIdentifierToAttachedViewMap[@(params.scopeIdentifier)];
// If the component tree currently attached to the view is different from the one we want to attach
if (currentlyAttachedView != view) {
// 1 - If the component layout want to attach is currently attached somewhere else then detach it
[self _detachComponentLayoutFromView:currentlyAttachedView];
// 2 - Unmount the component tree currently in the view we want to attach our component layout to
[self _detachComponentLayoutFromView:view];
}
const auto &prevLayout = [&]() {
if (const auto layoutProvider = [self->_scopeIdentifierToLayoutProvider objectForKey:@(params.scopeIdentifier)]) {
return layoutProvider.rootLayout;
} else {
return CKComponentRootLayout {};
}
}();
// Mount the component tree on the view
const auto &layout = params.layoutProvider ? params.layoutProvider.rootLayout : CKComponentRootLayout {};
const auto attachState = mountComponentLayoutInView(layout,
prevLayout,
view,
params.scopeIdentifier,
params.boundsAnimation,
params.analyticsListener);
// Mark the view as attached and associates it to the right attach state
self->_scopeIdentifierToAttachedViewMap[@(params.scopeIdentifier)] = view;
// Save layout provider in map, it will be used for figuring out animations between two layouts.
[self->_scopeIdentifierToLayoutProvider setObject:params.layoutProvider
forKey:@(params.scopeIdentifier)];
CKSetAttachStateForView(view, attachState);
}