in RenderCore/CKMountableHelpers.mm [40:108]
CK::Component::MountResult CKPerformMount(std::unique_ptr<CKMountInfo> &mountInfo,
const RCLayout &layout,
const CKViewConfiguration &viewConfiguration,
const CK::Component::MountContext &context,
const id<CKMountable> supercomponent,
const CKMountCallbackFunction didAcquireViewFunction,
const CKMountCallbackFunction willRelinquishViewFunction,
const CKMountAnimationBlockCallbackFunction blockAnimationIfNeededFunction,
const CKMountAnimationUnblockCallbackFunction unblockAnimationFunction)
{
RCCAssertMainThread();
if (!mountInfo) {
mountInfo.reset(new CKMountInfo());
}
mountInfo->supercomponent = supercomponent;
UIView *v = context.viewManager->viewForConfiguration(layout.component.class, viewConfiguration);
if (v) {
auto const currentMountedComponent = (id<CKMountable>)CKMountedObjectForView(v);
BOOL didBlockAnimation = NO;
if (blockAnimationIfNeededFunction) {
didBlockAnimation = blockAnimationIfNeededFunction(currentMountedComponent, layout.component, context, viewConfiguration);
}
// Mount a view for the component if needed.
UIView *acquiredView = nil;
if (mountInfo->view != v) {
relinquishMountedView(mountInfo, layout.component, willRelinquishViewFunction); // First release our old view
[currentMountedComponent unmount]; // Then unmount old component (if any) from the new view
CKSetMountedObjectForView(v, layout.component);
CK::Component::AttributeApplicator::apply(v, viewConfiguration);
acquiredView = v;
mountInfo->view = v;
} else {
RCCAssert(currentMountedComponent == layout.component, @"");
}
@try {
CKSetViewPositionAndBounds(v, context, layout.size);
} @catch (NSException *exception) {
NSString *const componentBacktraceDescription =
RCComponentBacktraceDescription(RCComponentGenerateBacktrace(supercomponent));
NSString *const componentChildrenDescription = RCComponentChildrenDescription(layout.children);
RCCFatalWithCategory(exception.name, @"%@ raised %@ during mount: %@\n backtrace:%@ children:%@", layout.component.class, exception.name, exception.reason, componentBacktraceDescription, componentChildrenDescription);
}
mountInfo->viewContext = {v, {{0,0}, v.bounds.size}};
// If the mount process acquired a new view, trigger the didAcquireView callback.
if (acquiredView && didAcquireViewFunction) {
didAcquireViewFunction(layout.component, acquiredView);
}
if (didBlockAnimation && unblockAnimationFunction) {
unblockAnimationFunction();
}
return {.mountChildren = YES, .contextForChildren = context.childContextForSubview(v, didBlockAnimation)};
} else {
RCCAssertWithCategory(mountInfo->view == nil, layout.component.class,
@"%@ should not have a mounted %@ after previously being mounted without a view.\n%@",
layout.component.class,
[mountInfo->view class],
RCComponentBacktraceDescription(RCComponentGenerateBacktrace(layout.component)));
mountInfo->viewContext = {context.viewManager->view, {context.position, layout.size}};
return {.mountChildren = YES, .contextForChildren = context};
}
}