Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fb64399

Browse files
authored
iOS: Migrate PlatformViewsController to Objective-C (#56790)
This migrates PlatformViewController from C++ to Objective-C. Generally, we try to keep the embedder interfaces and components written in Objective-C except for the few places where C++ interfaces are requried to interface with engine APIs such as Shell and PlatformView (e.g. the PlatformViewIOS subclass). Now that the implementation is Objective-C, the class and file are renamed to match Objective-C naming conventions. This allows us to take advantage of ARC and weak references, which eliminates the need for std::shared_ptr, fml::WeakPtr etc. Further, this eliminates some particularly unintuitive behaviour wherein this class was owned via a std::shared_ptr held by FlutterEngine, and injected into many other classes (e.g. AccessibilityBridge) via a std::shared_ptr& reference -- such that only one instance of the std::shared_ptr actually ever existed, presumably to avoid std::shared_ptr refcounting overhead. Given that this overhead was only incurred a single time at engine initialisation, this seems like overkill. One might ask why it wasn't therefore held in a `std::unique_ptr` and a `std::unique_ptr&` reference passed around. Likely, this was because we wanted to take a `fml::WeakPtr` reference on it. Regardless, none of this is necessary any longer now that we can inject `__weak FlutterPlatformViewsController*` instances to classes that use it. To be clear, this patch makes no attempt whatsoever to simplify or clean up the interface or implementation of this class. This class ties together far too many concepts and is injected into far too many places, and we should break it up and simplify it. However, the goal of this patch was simply to port to an Objective-C interface that plays nicely with the rest of the iOS embedder. This does include a couple minor cleanups in `#include`/`#import` order and usage to match our style guide. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 8ad5709 commit fb64399

24 files changed

Lines changed: 2293 additions & 1974 deletions

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44563,6 +44563,8 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverl
4456344563
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h + ../../../flutter/LICENSE
4456444564
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm + ../../../flutter/LICENSE
4456544565
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm + ../../../flutter/LICENSE
44566+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h + ../../../flutter/LICENSE
44567+
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm + ../../../flutter/LICENSE
4456644568
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm + ../../../flutter/LICENSE
4456744569
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h + ../../../flutter/LICENSE
4456844570
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm + ../../../flutter/LICENSE
@@ -44625,8 +44627,6 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_laye
4462544627
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm + ../../../flutter/LICENSE
4462644628
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h + ../../../flutter/LICENSE
4462744629
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm + ../../../flutter/LICENSE
44628-
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h + ../../../flutter/LICENSE
44629-
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm + ../../../flutter/LICENSE
4463044630
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h + ../../../flutter/LICENSE
4463144631
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.mm + ../../../flutter/LICENSE
4463244632
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h + ../../../flutter/LICENSE
@@ -47499,6 +47499,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlay
4749947499
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h
4750047500
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.mm
4750147501
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPluginTest.mm
47502+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.h
47503+
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsController.mm
4750247504
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm
4750347505
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h
4750447506
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.mm
@@ -47561,8 +47563,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_
4756147563
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm
4756247564
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h
4756347565
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm
47564-
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.h
47565-
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_views_controller.mm
4756647566
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h
4756747567
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.mm
4756847568
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h

shell/platform/darwin/ios/BUILD.gn

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ source_set("flutter_framework_source") {
7979
"framework/Source/FlutterOverlayView.mm",
8080
"framework/Source/FlutterPlatformPlugin.h",
8181
"framework/Source/FlutterPlatformPlugin.mm",
82+
"framework/Source/FlutterPlatformViewsController.h",
83+
"framework/Source/FlutterPlatformViewsController.mm",
8284
"framework/Source/FlutterPlatformViews_Internal.h",
8385
"framework/Source/FlutterPlatformViews_Internal.mm",
8486
"framework/Source/FlutterPluginAppLifeCycleDelegate.mm",
@@ -120,8 +122,6 @@ source_set("flutter_framework_source") {
120122
"framework/Source/overlay_layer_pool.mm",
121123
"framework/Source/platform_message_response_darwin.h",
122124
"framework/Source/platform_message_response_darwin.mm",
123-
"framework/Source/platform_views_controller.h",
124-
"framework/Source/platform_views_controller.mm",
125125
"framework/Source/profiler_metrics_ios.h",
126126
"framework/Source/profiler_metrics_ios.mm",
127127
"framework/Source/vsync_waiter_ios.h",

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

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ @interface FlutterEngine () <FlutterIndirectScribbleDelegate,
105105
@property(nonatomic, readonly, assign) BOOL allowHeadlessExecution;
106106
@property(nonatomic, readonly, assign) BOOL restorationEnabled;
107107

108+
@property(nonatomic, strong) FlutterPlatformViewsController* platformViewsController;
109+
108110
// Maintains a dictionary of plugin names that have registered with the engine. Used by
109111
// FlutterEngineRegistrar to implement a FlutterPluginRegistrar.
110112
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
@@ -150,7 +152,6 @@ @implementation FlutterEngine {
150152
std::shared_ptr<flutter::ThreadHost> _threadHost;
151153
std::unique_ptr<flutter::Shell> _shell;
152154

153-
std::shared_ptr<flutter::PlatformViewsController> _platformViewsController;
154155
flutter::IOSRenderingAPI _renderingApi;
155156
std::shared_ptr<flutter::SamplingProfiler> _profiler;
156157

@@ -211,7 +212,7 @@ - (instancetype)initWithName:(NSString*)labelPrefix
211212

212213
_pluginPublications = [[NSMutableDictionary alloc] init];
213214
_registrars = [[NSMutableDictionary alloc] init];
214-
[self recreatePlatformViewController];
215+
[self recreatePlatformViewsController];
215216
_binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self];
216217
_textureRegistry = [[FlutterTextureRegistryRelay alloc] initWithParent:self];
217218
_connections.reset(new flutter::ConnectionCollection());
@@ -262,9 +263,9 @@ - (void)setUpApplicationLifecycleNotifications:(NSNotificationCenter*)center {
262263
object:nil];
263264
}
264265

265-
- (void)recreatePlatformViewController {
266+
- (void)recreatePlatformViewsController {
266267
_renderingApi = flutter::GetRenderingAPIForProcess(FlutterView.forceSoftwareRendering);
267-
_platformViewsController.reset(new flutter::PlatformViewsController());
268+
_platformViewsController = [[FlutterPlatformViewsController alloc] init];
268269
}
269270

270271
- (flutter::IOSRenderingAPI)platformViewsRenderingAPI {
@@ -452,11 +453,7 @@ - (void)destroyContext {
452453
_shell.reset();
453454
_profiler.reset();
454455
_threadHost.reset();
455-
_platformViewsController.reset();
456-
}
457-
458-
- (std::shared_ptr<flutter::PlatformViewsController>&)platformViewsController {
459-
return _platformViewsController;
456+
_platformViewsController = nil;
460457
}
461458

462459
- (NSURL*)observatoryUrl {
@@ -635,7 +632,7 @@ - (void)maybeSetupPlatformViewChannels {
635632
[self.platformViewsChannel
636633
setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
637634
if (weakSelf) {
638-
weakSelf.platformViewsController->OnMethodCall(call, result);
635+
[weakSelf.platformViewsController onMethodCall:call result:result];
639636
}
640637
}];
641638

@@ -777,11 +774,11 @@ - (BOOL)createShell:(NSString*)entrypoint
777774
if (!strongSelf) {
778775
return std::unique_ptr<flutter::PlatformViewIOS>();
779776
}
780-
[strongSelf recreatePlatformViewController];
781-
strongSelf->_platformViewsController->SetTaskRunner(
782-
shell.GetTaskRunners().GetPlatformTaskRunner());
777+
[strongSelf recreatePlatformViewsController];
778+
strongSelf.platformViewsController.taskRunner =
779+
shell.GetTaskRunners().GetPlatformTaskRunner();
783780
return std::make_unique<flutter::PlatformViewIOS>(
784-
shell, strongSelf->_renderingApi, strongSelf->_platformViewsController,
781+
shell, strongSelf->_renderingApi, strongSelf.platformViewsController,
785782
shell.GetTaskRunners(), shell.GetConcurrentWorkerTaskRunner(),
786783
shell.GetIsGpuDisabledSyncSwitch());
787784
};
@@ -1103,7 +1100,7 @@ - (void)flutterTextInputView:(FlutterTextInputView*)textInputView
11031100
// Have to check in the next run loop, because iOS requests the previous first responder to
11041101
// resign before requesting the next view to become first responder.
11051102
dispatch_async(dispatch_get_main_queue(), ^(void) {
1106-
long platform_view_id = self.platformViewsController->FindFirstResponderPlatformViewId();
1103+
long platform_view_id = [self.platformViewsController firstResponderPlatformViewId];
11071104
if (platform_view_id == -1) {
11081105
return;
11091106
}
@@ -1400,11 +1397,10 @@ - (FlutterEngine*)spawnWithEntrypoint:(/*nullable*/ NSString*)entrypoint
14001397
// create call is synchronous.
14011398
flutter::Shell::CreateCallback<flutter::PlatformView> on_create_platform_view =
14021399
[result, context](flutter::Shell& shell) {
1403-
[result recreatePlatformViewController];
1404-
result->_platformViewsController->SetTaskRunner(
1405-
shell.GetTaskRunners().GetPlatformTaskRunner());
1400+
[result recreatePlatformViewsController];
1401+
result.platformViewsController.taskRunner = shell.GetTaskRunners().GetPlatformTaskRunner();
14061402
return std::make_unique<flutter::PlatformViewIOS>(
1407-
shell, context, result->_platformViewsController, shell.GetTaskRunners());
1403+
shell, context, result.platformViewsController, shell.GetTaskRunners());
14081404
};
14091405

14101406
flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer =
@@ -1499,8 +1495,9 @@ - (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
14991495
withId:(NSString*)factoryId
15001496
gestureRecognizersBlockingPolicy:
15011497
(FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizersBlockingPolicy {
1502-
[_flutterEngine platformViewsController]->RegisterViewFactory(factory, factoryId,
1503-
gestureRecognizersBlockingPolicy);
1498+
[_flutterEngine.platformViewsController registerViewFactory:factory
1499+
withId:factoryId
1500+
gestureRecognizersBlockingPolicy:gestureRecognizersBlockingPolicy];
15041501
}
15051502

15061503
@end

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ NS_ASSUME_NONNULL_BEGIN
4646
base64Encode:(bool)base64Encode;
4747

4848
- (FlutterPlatformPlugin*)platformPlugin;
49-
- (std::shared_ptr<flutter::PlatformViewsController>&)platformViewsController;
5049
- (FlutterTextInputPlugin*)textInputPlugin;
5150
- (FlutterRestorationPlugin*)restorationPlugin;
5251
- (void)launchEngine:(nullable NSString*)entrypoint
@@ -81,6 +80,7 @@ NS_ASSUME_NONNULL_BEGIN
8180
userData:(nullable void*)userData;
8281

8382
@property(nonatomic, readonly) FlutterDartProject* project;
83+
8484
@end
8585

8686
NS_ASSUME_NONNULL_END
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_
6+
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_
7+
8+
#include <Metal/Metal.h>
9+
#include <memory>
10+
#include <unordered_map>
11+
#include <unordered_set>
12+
13+
#include "flutter/flow/surface.h"
14+
#include "flutter/fml/task_runner.h"
15+
#include "flutter/fml/trace_event.h"
16+
#include "impeller/base/thread_safety.h"
17+
#include "third_party/skia/include/core/SkRect.h"
18+
19+
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
20+
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
21+
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h"
22+
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewResponder.h"
23+
#import "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
24+
#import "flutter/shell/platform/darwin/ios/ios_context.h"
25+
26+
@class FlutterTouchInterceptingView;
27+
@class FlutterClippingMaskViewPool;
28+
29+
@interface FlutterPlatformViewsController : NSObject
30+
31+
- (id)init NS_DESIGNATED_INITIALIZER;
32+
33+
/// The task runner used to post rendering tasks to the platform thread.
34+
@property(nonatomic, assign) const fml::RefPtr<fml::TaskRunner>& taskRunner;
35+
36+
/// The flutter view.
37+
@property(nonatomic, weak) UIView* flutterView;
38+
39+
/// @brief The flutter view controller.
40+
@property(nonatomic, weak) UIViewController<FlutterViewResponder>* flutterViewController;
41+
42+
/// @brief Retrieve the view controller.
43+
- (UIViewController<FlutterViewResponder>*)flutterViewController;
44+
45+
/// @brief set the factory used to construct embedded UI Views.
46+
- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
47+
withId:(NSString*)factoryId
48+
gestureRecognizersBlockingPolicy:
49+
(FlutterPlatformViewGestureRecognizersBlockingPolicy)gestureRecognizerBlockingPolicy;
50+
51+
/// @brief Mark the beginning of a frame and record the size of the onscreen.
52+
- (void)beginFrameWithSize:(SkISize)frameSize;
53+
54+
/// @brief Cancel the current frame, indicating that no platform views are composited.
55+
///
56+
/// Additionally, reverts the composition order to its original state at the beginning of the
57+
/// frame.
58+
- (void)cancelFrame;
59+
60+
/// @brief Record a platform view in the layer tree to be rendered, along with the positioning and
61+
/// mutator parameters.
62+
///
63+
/// Called from the raster thread.
64+
- (void)prerollCompositeEmbeddedView:(int64_t)viewId
65+
withParams:(std::unique_ptr<flutter::EmbeddedViewParams>)params;
66+
67+
/// @brief Returns the`FlutterTouchInterceptingView` with the provided view_id.
68+
///
69+
/// Returns nil if there is no platform view with the provided id. Called
70+
/// from the platform thread.
71+
- (FlutterTouchInterceptingView*)flutterTouchInterceptingViewForId:(int64_t)viewId;
72+
73+
/// @brief Determine if thread merging is required after prerolling platform views.
74+
///
75+
/// Called from the raster thread.
76+
- (flutter::PostPrerollResult)postPrerollActionWithThreadMerger:
77+
(const fml::RefPtr<fml::RasterThreadMerger>&)rasterThreadMerger
78+
impellerEnabled:(BOOL)impellerEnabled;
79+
80+
/// @brief Mark the end of a compositor frame.
81+
///
82+
/// May determine changes are required to the thread merging state.
83+
/// Called from the raster thread.
84+
- (void)endFrameWithResubmit:(BOOL)shouldResubmitFrame
85+
threadMerger:(const fml::RefPtr<fml::RasterThreadMerger>&)rasterThreadMerger
86+
impellerEnabled:(BOOL)impellerEnabled;
87+
88+
/// @brief Returns the Canvas for the overlay slice for the given platform view.
89+
///
90+
/// Called from the raster thread.
91+
- (flutter::DlCanvas*)compositeEmbeddedViewWithId:(int64_t)viewId;
92+
93+
/// @brief Discards all platform views instances and auxiliary resources.
94+
///
95+
/// Called from the raster thread.
96+
- (void)reset;
97+
98+
/// @brief Encode rendering for the Flutter overlay views and queue up perform platform view
99+
/// mutations.
100+
///
101+
/// Called from the raster thread.
102+
- (BOOL)submitFrame:(std::unique_ptr<flutter::SurfaceFrame>)frame
103+
withIosContext:(const std::shared_ptr<flutter::IOSContext>&)iosContext
104+
grContext:(GrDirectContext*)grContext;
105+
106+
/// @brief Handler for platform view message channels.
107+
- (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result;
108+
109+
/// @brief Returns the platform view id if the platform view (or any of its descendant view) is
110+
/// the first responder.
111+
///
112+
/// Returns -1 if no such platform view is found.
113+
- (long)firstResponderPlatformViewId;
114+
115+
/// @brief Pushes backdrop filter mutation to the mutator stack of each visited platform view.
116+
- (void)pushFilterToVisitedPlatformViews:(const std::shared_ptr<flutter::DlImageFilter>&)filter
117+
withRect:(const SkRect&)filterRect;
118+
119+
/// @brief Pushes the view id of a visted platform view to the list of visied platform views.
120+
- (void)pushVisitedPlatformViewId:(int64_t)viewId;
121+
122+
@end
123+
124+
@interface FlutterPlatformViewsController (Testing)
125+
126+
- (size_t)embeddedViewCount;
127+
128+
// TODO(cbracken): Delete. This is unused.
129+
- (size_t)layerPoolSize;
130+
131+
// Returns the `FlutterPlatformView`'s `view` object associated with the view_id.
132+
//
133+
// If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or
134+
// a `FlutterPlatformView` object associated with the view_id cannot be found, the method
135+
// returns nil.
136+
- (UIView*)platformViewForId:(int64_t)viewId;
137+
138+
// Composite the PlatformView with `viewId`.
139+
//
140+
// Every frame, during the paint traversal of the layer tree, this method is called for all
141+
// the PlatformViews in `_viewsToRecomposite`.
142+
//
143+
// Note that `_viewsToRecomposite` does not represent all the views in the view hierarchy,
144+
// if a PlatformView does not change its composition parameter from last frame, it is not
145+
// included in the `views_to_recomposite_`.
146+
- (void)compositeView:(int64_t)viewId withParams:(const flutter::EmbeddedViewParams&)params;
147+
148+
- (const flutter::EmbeddedViewParams&)compositionParamsForView:(int64_t)viewId;
149+
150+
@end
151+
152+
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWSCONTROLLER_H_

0 commit comments

Comments
 (0)