1/* 2 * Copyright (c) Meta Platforms, Inc. and affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 */ 7 8#import "ABI48_0_0RCTWrapperViewControllerHostingView.h" 9 10#import <ABI48_0_0React/ABI48_0_0UIView+React.h> 11 12#pragma mark - UIViewController+Children 13 14@interface UIViewController (Children) 15 16@property (nonatomic, readonly) BOOL isAttached; 17- (void)attachChildViewController:(UIViewController *)childViewController toContainerView:(UIView *)containerView; 18- (void)detachChildViewController:(UIViewController *)childViewController; 19 20@end 21 22@implementation UIViewController (Children) 23 24- (BOOL)isAttached 25{ 26 return self.parentViewController != nil; 27} 28 29- (void)attachChildViewController:(UIViewController *)childViewController toContainerView:(UIView *)containerView 30{ 31 [self addChildViewController:childViewController]; 32 // `[childViewController willMoveToParentViewController:self]` is calling automatically 33 [containerView addSubview:childViewController.view]; 34 childViewController.view.frame = containerView.bounds; 35 childViewController.view.translatesAutoresizingMaskIntoConstraints = YES; 36 childViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 37 [childViewController didMoveToParentViewController:self]; 38 39 [childViewController beginAppearanceTransition:true animated:false]; 40 [childViewController endAppearanceTransition]; 41} 42 43- (void)detachChildViewController:(UIViewController *)childViewController 44{ 45 [childViewController beginAppearanceTransition:false animated:false]; 46 [childViewController endAppearanceTransition]; 47 48 [childViewController willMoveToParentViewController:nil]; 49 [childViewController.view removeFromSuperview]; 50 [childViewController removeFromParentViewController]; 51 // `[childViewController didMoveToParentViewController:nil]` is calling automatically 52} 53 54@end 55 56@implementation ABI48_0_0RCTWrapperViewControllerHostingView { 57 UIViewController *_Nullable _contentViewController; 58} 59 60#pragma mark - `contentViewController` 61 62- (nullable UIViewController *)contentViewController 63{ 64 return _contentViewController; 65} 66 67- (void)setContentViewController:(UIViewController *)contentViewController 68{ 69 if (_contentViewController) { 70 [self detachContentViewControllerIfNeeded]; 71 } 72 73 _contentViewController = contentViewController; 74 75 if (_contentViewController) { 76 [self attachContentViewControllerIfNeeded]; 77 } 78} 79 80#pragma mark - Attaching and Detaching 81 82- (void)attachContentViewControllerIfNeeded 83{ 84 if (self.contentViewController.isAttached) { 85 return; 86 } 87 88 [self.ABI48_0_0ReactViewController attachChildViewController:self.contentViewController toContainerView:self]; 89} 90 91- (void)detachContentViewControllerIfNeeded 92{ 93 if (!self.contentViewController.isAttached) { 94 return; 95 } 96 97 [self.ABI48_0_0ReactViewController detachChildViewController:self.contentViewController]; 98} 99 100#pragma mark - Life cycle 101 102- (void)willMoveToWindow:(UIWindow *)newWindow 103{ 104 if (newWindow == nil) { 105 [self detachContentViewControllerIfNeeded]; 106 } 107} 108 109- (void)didMoveToWindow 110{ 111 [super didMoveToWindow]; 112 [self attachContentViewControllerIfNeeded]; 113} 114 115#pragma mark - Layout 116 117- (void)setNeedsLayout 118{ 119 [super setNeedsLayout]; 120 [self.superview setNeedsLayout]; 121} 122 123- (CGSize)intrinsicContentSize 124{ 125 return self.contentViewController.view.intrinsicContentSize; 126} 127 128- (CGSize)sizeThatFits:(CGSize)size 129{ 130 return [self.contentViewController.view sizeThatFits:size]; 131} 132 133@end 134