Skip to content

Commit a0efb94

Browse files
authored
Make the FlutterPlatformViewFactory create FlutterPlatformViews. (#6782)
Handing a UIView refererence directly to the engine makes it challenging for plugin authors to retain a controller for that UIView (e.g the controller that talks over the platform channel) for as long as the embedded view is needed. We instead make the factory return a FlutterPlatformView which is a wrapper around the UIView that the engine retains as long as the platform view instance is needed. This allows plugin authors to keep their control logic in the FlutterPlatformView and know that the engine is responsible for retaining the reference.
1 parent 7ed4909 commit a0efb94

4 files changed

Lines changed: 35 additions & 20 deletions

File tree

shell/common/rasterizer.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,10 +164,9 @@ bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
164164

165165
auto external_view_embedder = surface_->GetExternalViewEmbedder();
166166

167-
// TODO(amirh): uncomment this once external_view_embedder is populated.
168-
// if (external_view_embedder != nullptr) {
169-
// external_view_embedder->SetFrameSize(layer_tree.frame_size());
170-
// }
167+
if (external_view_embedder != nullptr) {
168+
external_view_embedder->SetFrameSize(layer_tree.frame_size());
169+
}
171170

172171
auto compositor_frame = compositor_context_->AcquireFrame(
173172
surface_->GetContext(), canvas, external_view_embedder,

shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,16 @@
1212

1313
NS_ASSUME_NONNULL_BEGIN
1414

15+
/**
16+
* Wraps a `UIView` for embedding in the Flutter hierarchy
17+
*/
18+
@protocol FlutterPlatformView <NSObject>
19+
/**
20+
* Returns a reference to the `UIView` that is wrapped by this `FlutterPlatformView`.
21+
*/
22+
- (UIView*)view;
23+
@end
24+
1525
FLUTTER_EXPORT
1626
@protocol FlutterPlatformViewFactory <NSObject>
1727
/**
@@ -28,9 +38,9 @@ FLUTTER_EXPORT
2838
* code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by
2939
* `createArgsCodec`.
3040
*/
31-
- (UIView*)createWithFrame:(CGRect)frame
32-
viewIdentifier:(int64_t)viewId
33-
arguments:(id _Nullable)args;
41+
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
42+
viewIdentifier:(int64_t)viewId
43+
arguments:(id _Nullable)args;
3444

3545
/**
3646
* Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,17 @@
7272
}
7373
}
7474

75-
UIView* embedded_view = [factory createWithFrame:CGRectZero
76-
viewIdentifier:viewId
77-
arguments:params];
78-
FlutterTouchInterceptingView* view =
79-
[[[FlutterTouchInterceptingView alloc] initWithEmbeddedView:embedded_view
75+
NSObject<FlutterPlatformView>* embedded_view = [factory createWithFrame:CGRectZero
76+
viewIdentifier:viewId
77+
arguments:params];
78+
views_[viewId] = fml::scoped_nsobject<NSObject<FlutterPlatformView>>([embedded_view retain]);
79+
80+
FlutterTouchInterceptingView* touch_interceptor =
81+
[[[FlutterTouchInterceptingView alloc] initWithEmbeddedView:embedded_view.view
8082
flutterView:flutter_view_] autorelease];
81-
views_[viewId] = fml::scoped_nsobject<FlutterTouchInterceptingView>([view retain]);
83+
84+
touch_interceptors_[viewId] =
85+
fml::scoped_nsobject<FlutterTouchInterceptingView>([touch_interceptor retain]);
8286

8387
result(nil);
8488
}
@@ -94,9 +98,10 @@
9498
return;
9599
}
96100

97-
UIView* view = views_[viewId].get();
98-
[view removeFromSuperview];
101+
UIView* touch_interceptor = touch_interceptors_[viewId].get();
102+
[touch_interceptor removeFromSuperview];
99103
views_.erase(viewId);
104+
touch_interceptors_.erase(viewId);
100105
overlays_.erase(viewId);
101106
result(nil);
102107
}
@@ -113,7 +118,7 @@
113118
return;
114119
}
115120

116-
FlutterTouchInterceptingView* view = views_[viewId].get();
121+
FlutterTouchInterceptingView* view = touch_interceptors_[viewId].get();
117122
[view releaseGesture];
118123

119124
result(nil);
@@ -159,8 +164,8 @@
159164
CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale,
160165
params.sizePoints.width(), params.sizePoints.height());
161166

162-
UIView* view = views_[view_id].get();
163-
[view setFrame:rect];
167+
UIView* touch_interceptor = touch_interceptors_[view_id].get();
168+
[touch_interceptor setFrame:rect];
164169

165170
SkCanvas* canvas = composition_frames_[view_id]->SkiaCanvas();
166171
canvas->clear(SK_ColorTRANSPARENT);
@@ -204,7 +209,7 @@
204209
active_composition_order_.clear();
205210
for (size_t i = 0; i < composition_order_.size(); i++) {
206211
int view_id = composition_order_[i];
207-
[flutter_view addSubview:views_[view_id].get()];
212+
[flutter_view addSubview:touch_interceptors_[view_id].get()];
208213
[flutter_view addSubview:overlays_[view_id]->overlay_view.get()];
209214
active_composition_order_.push_back(view_id);
210215
}

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ class FlutterPlatformViewsController {
7070
fml::scoped_nsobject<FlutterMethodChannel> channel_;
7171
fml::scoped_nsobject<UIView> flutter_view_;
7272
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
73-
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> views_;
73+
std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_;
74+
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_;
7475
std::map<int64_t, std::unique_ptr<FlutterPlatformViewLayer>> overlays_;
7576
SkISize frame_size_;
7677

0 commit comments

Comments
 (0)