diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 35cf9553b0c61..c7cca212714fa 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -394,7 +394,6 @@ - (void)maybeSetupPlatformViewChannels { [_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { [_textInputPlugin.get() handleMethodCall:call result:result]; }]; - self.iosPlatformView->SetTextInputPlugin(_textInputPlugin); } } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index d051ff0038874..ea8afcf06e49d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -417,10 +417,6 @@ - (void)installFirstFrameCallback { #pragma mark - Properties -- (FlutterView*)flutterView { - return _flutterView; -} - - (UIView*)splashScreenView { if (!_splashScreenView) { return nil; @@ -515,8 +511,8 @@ - (void)viewDidLoad { _engineNeedsLaunch = NO; } - FML_DCHECK([_engine.get() viewController] != nil) - << "FlutterViewController::viewWillAppear:AttachView ViewController was nil"; + FML_DCHECK([_engine.get() viewController] == self) + << "FlutterViewController's view is loaded but is not attached to a FlutterEngine"; [_engine.get() attachView]; [super viewDidLoad]; diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h index 7a990d965fc0b..cbb08421e17ac 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h @@ -27,6 +27,13 @@ namespace flutter { class PlatformViewIOS; +/** + * An accessibility instance is bound to one `FlutterViewController` and + * `FlutterView` instance. + * + * It helps populate the UIView's accessibilityElements property from Flutter's + * semantics nodes. + */ class AccessibilityBridge final : public AccessibilityBridgeIos { public: AccessibilityBridge(UIView* view, diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm index c9c147bdacc55..78f157381c182 100644 --- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm +++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm @@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h" -#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" +#import "flutter/shell/platform/darwin/ios/platform_view_ios.h" #pragma GCC diagnostic error "-Wundeclared-selector" @@ -38,7 +39,7 @@ } UIView* AccessibilityBridge::textInputView() { - return [platform_view_->GetTextInputPlugin() textInputView]; + return [[platform_view_->GetOwnerViewController().get().engine textInputPlugin] textInputView]; } void AccessibilityBridge::UpdateSemantics(flutter::SemanticsNodeUpdates nodes, diff --git a/shell/platform/darwin/ios/platform_view_ios.h b/shell/platform/darwin/ios/platform_view_ios.h index 95f6fc0ecfacf..a89192d908ca5 100644 --- a/shell/platform/darwin/ios/platform_view_ios.h +++ b/shell/platform/darwin/ios/platform_view_ios.h @@ -25,6 +25,18 @@ namespace flutter { +/** + * A bridge connecting the platform agnostic shell and the iOS embedding. + * + * The shell provides and requests for UI related data and this PlatformView subclass fulfills + * it with iOS specific capabilities. As an example, the iOS embedding (the `FlutterEngine` and the + * `FlutterViewController`) sends pointer data to the shell and receives the shell's request for a + * Skia GrContext and supplies it. + * + * Despite the name "view", this class is unrelated to UIViews on iOS and doesn't have the same + * lifecycle. It's a long lived bridge owned by the `FlutterEngine` and can be attached and + * detached sequentially to multiple `FlutterViewController`s and `FlutterView`s. + */ class PlatformViewIOS final : public PlatformView { public: explicit PlatformViewIOS(PlatformView::Delegate& delegate, @@ -33,21 +45,43 @@ class PlatformViewIOS final : public PlatformView { ~PlatformViewIOS() override; + /** + * The `PlatformMessageRouter` is the iOS bridge connecting the shell's + * platform agnostic `PlatformMessage` to iOS's channel message handler. + */ PlatformMessageRouter& GetPlatformMessageRouter(); + /** + * Returns the `FlutterViewController` currently attached to the `FlutterEngine` owning + * this PlatformViewIOS. + */ fml::WeakPtr GetOwnerViewController() const; + + /** + * Updates the `FlutterViewController` currently attached to the `FlutterEngine` owning + * this PlatformViewIOS. This should be updated when the `FlutterEngine` + * is given a new `FlutterViewController`. + */ void SetOwnerViewController(fml::WeakPtr owner_controller); + + /** + * Called one time per `FlutterViewController` when the `FlutterViewController`'s + * UIView is first loaded. + * + * Can be used to perform late initialization after `FlutterViewController`'s + * init. + */ void attachView(); + /** + * Called through when an external texture such as video or camera is + * given to the `FlutterEngine` or `FlutterViewController`. + */ void RegisterExternalTexture(int64_t id, NSObject* texture); // |PlatformView| PointerDataDispatcherMaker GetDispatcherMaker() override; - fml::scoped_nsprotocol GetTextInputPlugin() const; - - void SetTextInputPlugin(fml::scoped_nsprotocol plugin); - // |PlatformView| void SetSemanticsEnabled(bool enabled) override; diff --git a/shell/platform/darwin/ios/platform_view_ios.mm b/shell/platform/darwin/ios/platform_view_ios.mm index 772d5775bab6f..d2f4cb48a26bd 100644 --- a/shell/platform/darwin/ios/platform_view_ios.mm +++ b/shell/platform/darwin/ios/platform_view_ios.mm @@ -10,8 +10,8 @@ #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/fml/trace_event.h" #include "flutter/shell/common/shell_io_manager.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" +#import "flutter/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h" namespace flutter { @@ -99,6 +99,9 @@ void PlatformViewIOS::attachView() { FML_DCHECK(owner_controller_); + FML_DCHECK(owner_controller_.get().isViewLoaded) + << "FlutterViewController's view should be loaded " + "before attaching to PlatformViewIOS."; ios_surface_ = [static_cast(owner_controller_.get().view) createSurface:ios_context_]; FML_DCHECK(ios_surface_ != nullptr); @@ -188,14 +191,6 @@ new AccessibilityBridge(static_cast(owner_controller_.get().view), [owner_controller_.get() platformViewsController]->Reset(); } -fml::scoped_nsprotocol PlatformViewIOS::GetTextInputPlugin() const { - return text_input_plugin_; -} - -void PlatformViewIOS::SetTextInputPlugin(fml::scoped_nsprotocol plugin) { - text_input_plugin_ = plugin; -} - PlatformViewIOS::ScopedObserver::ScopedObserver() : observer_(nil) {} PlatformViewIOS::ScopedObserver::~ScopedObserver() {