UNPKG

3.78 kBPlain TextView Raw
1/**
2 * Copyright (c) Facebook, Inc. and its 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 "RCTSurfaceHostingComponentController.h"
9
10#import <ComponentKit/CKComponentSubclass.h>
11#import <React/RCTAssert.h>
12#import <React/RCTSurface.h>
13#import <React/RCTSurfaceDelegate.h>
14#import <React/RCTSurfaceView.h>
15
16#import "RCTSurfaceHostingComponent+Internal.h"
17#import "RCTSurfaceHostingComponent.h"
18#import "RCTSurfaceHostingComponentState.h"
19
20@interface RCTSurfaceHostingComponentController() <RCTSurfaceDelegate>
21@end
22
23@implementation RCTSurfaceHostingComponentController {
24 RCTSurface *_surface;
25}
26
27- (instancetype)initWithComponent:(RCTSurfaceHostingComponent *)component
28{
29 if (self = [super initWithComponent:component]) {
30 [self updateSurfaceWithComponent:component];
31 }
32
33 return self;
34}
35
36#pragma mark - Lifecycle
37
38- (void)didMount
39{
40 [super didMount];
41 [self mountSurfaceView];
42}
43
44- (void)didRemount
45{
46 [super didRemount];
47 [self mountSurfaceView];
48}
49
50- (void)didUpdateComponent
51{
52 [super didUpdateComponent];
53 [self updateSurfaceWithComponent:(RCTSurfaceHostingComponent *)self.component];
54}
55
56- (void)didUnmount
57{
58 [super didUnmount];
59 [self unmountSurfaceView];
60}
61
62#pragma mark - Helpers
63
64- (void)updateSurfaceWithComponent:(RCTSurfaceHostingComponent *)component
65{
66 // Updating `surface`
67 RCTSurface *const surface = component.surface;
68 if (surface != _surface) {
69 if (_surface.delegate == self) {
70 _surface.delegate = nil;
71 }
72
73 _surface = surface;
74 _surface.delegate = self;
75 }
76}
77
78- (void)setIntrinsicSize:(CGSize)intrinsicSize
79{
80 [self.component updateState:^(RCTSurfaceHostingComponentState *state) {
81 return [RCTSurfaceHostingComponentState newWithStage:state.stage
82 intrinsicSize:intrinsicSize];
83 } mode:[self suitableStateUpdateMode]];
84}
85
86- (void)setStage:(RCTSurfaceStage)stage
87{
88 [self.component updateState:^(RCTSurfaceHostingComponentState *state) {
89 return [RCTSurfaceHostingComponentState newWithStage:stage
90 intrinsicSize:state.intrinsicSize];
91 } mode:[self suitableStateUpdateMode]];
92}
93
94- (CKUpdateMode)suitableStateUpdateMode
95{
96 return ((RCTSurfaceHostingComponent *)self.component).options.synchronousStateUpdates && RCTIsMainQueue() ? CKUpdateModeSynchronous : CKUpdateModeAsynchronous;
97}
98
99- (void)mountSurfaceView
100{
101 UIView *const surfaceView = _surface.view;
102
103 const CKComponentViewContext &context = [[self component] viewContext];
104
105 UIView *const superview = context.view;
106 superview.clipsToBounds = YES;
107
108 RCTAssert([superview.subviews count] <= 1, @"Should never have more than a single stateful subview.");
109
110 UIView *const existingSurfaceView = [superview.subviews lastObject];
111 if (existingSurfaceView != surfaceView) {
112 [existingSurfaceView removeFromSuperview];
113 surfaceView.frame = superview.bounds;
114 surfaceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
115 [superview addSubview:surfaceView];
116 }
117}
118
119- (void)unmountSurfaceView
120{
121 const CKComponentViewContext &context = [[self component] viewContext];
122
123 UIView *const superview = context.view;
124 RCTAssert([superview.subviews count] <= 1, @"Should never have more than a single stateful subview.");
125 UIView *const existingSurfaceView = [superview.subviews lastObject];
126 [existingSurfaceView removeFromSuperview];
127}
128
129#pragma mark - RCTSurfaceDelegate
130
131- (void)surface:(RCTSurface *)surface didChangeIntrinsicSize:(CGSize)intrinsicSize
132{
133 [self setIntrinsicSize:intrinsicSize];
134}
135
136- (void)surface:(RCTSurface *)surface didChangeStage:(RCTSurfaceStage)stage
137{
138 [self setStage:stage];
139}
140
141@end