From 96388d606a3608c8665455a89bbc1f025cc55e4a Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Mon, 15 Oct 2018 14:13:20 -0700 Subject: [PATCH 1/5] Add an iOS PlatformViewsController for creating/disposing UIViews. * Adds a FlutterPlatformViewFactory protocol - a simple factory protocol to be implemented by plugins that exposes a UIView for embeeding in Flutter apps. * Adds a FlutterPlatformView protocol, which is used to associate a dispose callback with a `UIView` created by a FlutterPlatformViewFactory. * Exposes a registerViewFactory method in FlutterPluginRegistrar. * Implements the `flutter/platform_views` system channel on iOS, allowing Dart code to ask for creation/destruction of UIViews. --- ci/licenses_golden/licenses_flutter | 3 + shell/platform/darwin/ios/BUILD.gn | 3 + .../darwin/ios/framework/Headers/Flutter.h | 1 + .../framework/Headers/FlutterPlatformViews.h | 63 ++++++++++++ .../ios/framework/Headers/FlutterPlugin.h | 14 +++ .../framework/Source/FlutterPlatformViews.mm | 96 +++++++++++++++++++ .../Source/FlutterPlatformViews_Internal.h | 21 ++++ .../framework/Source/FlutterViewController.mm | 14 +++ 8 files changed, 215 insertions(+) create mode 100644 shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h create mode 100644 shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm create mode 100644 shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index acefd7e4a9672..217ad698cafed 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -521,6 +521,8 @@ FILE: ../../../flutter/shell/platform/android/platform_message_response_android. FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.mm FILE: ../../../flutter/shell/platform/embedder/embedder_surface.cc @@ -590,6 +592,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Virtual FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterCallbackInformation.java FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterRunArguments.java FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterCallbackCache.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache_Internal.h diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index f340f73e0eb6a..d33519ce0b712 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -29,6 +29,7 @@ _flutter_framework_headers = [ "framework/Headers/FlutterHeadlessDartRunner.h", "framework/Headers/FlutterMacros.h", "framework/Headers/FlutterNavigationController.h", + "framework/Headers/FlutterPlatformViews.h", "framework/Headers/FlutterPlugin.h", "framework/Headers/FlutterPluginAppLifeCycleDelegate.h", "framework/Headers/FlutterTexture.h", @@ -57,6 +58,8 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/FlutterObservatoryPublisher.mm", "framework/Source/FlutterPlatformPlugin.h", "framework/Source/FlutterPlatformPlugin.mm", + "framework/Source/FlutterPlatformViews_Internal.h", + "framework/Source/FlutterPlatformViews.mm", "framework/Source/FlutterPluginAppLifeCycleDelegate.mm", "framework/Source/FlutterStandardCodec.mm", "framework/Source/FlutterStandardCodec_Internal.h", diff --git a/shell/platform/darwin/ios/framework/Headers/Flutter.h b/shell/platform/darwin/ios/framework/Headers/Flutter.h index 49464e40dc06b..458db5ed3637b 100644 --- a/shell/platform/darwin/ios/framework/Headers/Flutter.h +++ b/shell/platform/darwin/ios/framework/Headers/Flutter.h @@ -50,6 +50,7 @@ #include "FlutterHeadlessDartRunner.h" #include "FlutterMacros.h" #include "FlutterNavigationController.h" +#include "FlutterPlatformViews.h" #include "FlutterPlugin.h" #include "FlutterPluginAppLifeCycleDelegate.h" #include "FlutterTexture.h" diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h new file mode 100644 index 0000000000000..33d08152a5512 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h @@ -0,0 +1,63 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_FLUTTERPLATFORMVIEWS_H_ +#define FLUTTER_FLUTTERPLATFORMVIEWS_H_ + +#import +#import +#import + +#include "FlutterCodecs.h" +#include "FlutterMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + An instance of a `UIView` created by a `FlutterPlatformViewFactory`. + + This protocol is used to associate a view with a dispose callback. + */ +FLUTTER_EXPORT +@protocol FlutterPlatformView +- (UIView*)view; +/** + Called when the Flutter engine no longer needs this `view`. + + The implementation of this method should release any kept for this view. + */ +- (void)dispose; +@end + +FLUTTER_EXPORT +@protocol FlutterPlatformViewFactory +/** + Create a `FlutterPlatformView`. + + Implemented by iOS code that expose a `UIView` for embedding in a Flutter app. + + The implementation of this method should create a new `UIView` and return a `FlutterPlatformView` + that wraps it. + + - Parameters: + - frame: The rectangle for the newly created `UIView` measued in points. + - args: Parameters for creating the `UIView` sent from the Dart side of the Flutter app. + If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart + code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by + `createArgsCodec`. + */ +- (NSObject*)createWithFrame:(CGRect)frame andArgs:(id _Nullable)args; + +/** + Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`. + + Only needs to be implemented if `createWithFrame` needs an arguments parameter. + */ +@optional +- (NSObject*)createArgsCodec; +@end + +NS_ASSUME_NONNULL_END + +#endif // FLUTTER_FLUTTERPLATFORMVIEWS_H_ diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h index 799aa90fa0b30..87cdbd3af28a7 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h @@ -10,6 +10,7 @@ #include "FlutterBinaryMessenger.h" #include "FlutterChannels.h" #include "FlutterCodecs.h" +#include "FlutterPlatformViews.h" #include "FlutterTexture.h" NS_ASSUME_NONNULL_BEGIN @@ -203,6 +204,19 @@ NS_ASSUME_NONNULL_BEGIN */ - (NSObject*)textures; +/** + Registers a `FlutterPlatformViewFactory` for creation of platfrom views. + + Plugins expose `UIView` for embedding in Flutter apps by registering a view factory. + + - Parameters: + - factory: The view factory that will be registered. + - factoryId:: A unique identifier for the factory, the Dart code of the Flutter app can use + this identifier to request creation of a `UIView` by the registered factory. + */ +- (void)registerViewFactory:(NSObject*)factory + withId:(NSString*)factoryId; + /** Publishes a value for external use of the plugin. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm new file mode 100644 index 0000000000000..8fe2c15b0db04 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -0,0 +1,96 @@ +// Copyright 2018 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "FlutterPlatformViews_Internal.h" +#include "flutter/fml/platform/darwin/scoped_nsobject.h" +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" + +@implementation FlutterPlatformViewsController { + fml::scoped_nsobject _channel; + std::map>> _factories; + std::map>> _views; +} + +- (instancetype)init:(NSObject*)withMessenger { + if (self = [super init]) { + _channel.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/platform_views" + binaryMessenger:withMessenger + codec:[FlutterStandardMethodCodec sharedInstance]]); + [_channel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + [self methodCallHandler:call withResult:result]; + }]; + } + return self; +} + +- (void)registerViewFactory:(NSObject*)factory + withId:(NSString*)factoryId { + std::string idString([factoryId UTF8String]); + NSAssert(_factories.count(idString) == 0, + ([NSString stringWithFormat:@"Can't register an already registered view factory: %@", + factoryId])); + _factories[idString] = + fml::scoped_nsobject>([factory retain]); +} + +- (void)methodCallHandler:(FlutterMethodCall*)call withResult:(FlutterResult)result { + if ([[call method] isEqualToString:@"create"]) { + [self handleCreate:call withResult:result]; + } else if ([[call method] isEqualToString:@"dispose"]) { + [self handleDispose:call withResult:result]; + } else { + result(FlutterMethodNotImplemented); + } +} + +- (void)handleCreate:(FlutterMethodCall*)call withResult:(FlutterResult)result { + NSDictionary* args = [call arguments]; + + long viewId = [args[@"id"] longValue]; + std::string viewType([args[@"viewType"] UTF8String]); + + if (_views[viewId] != nil) { + result([FlutterError errorWithCode:@"recreating_view" + message:@"trying to create an already created view" + details:[NSString stringWithFormat:@"view id: '%ld'", viewId]]); + } + + NSObject* factory = _factories[viewType].get(); + if (factory == nil) { + result([FlutterError errorWithCode:@"unregistered_view_type" + message:@"trying to create a view with an unregistered type" + details:[NSString stringWithFormat:@"unregistered view type: '%@'", + args[@"viewType"]]]); + return; + } + + // TODO(amirh): decode and pass the creation args. + _views[viewId] = + fml::scoped_nsobject>([[factory createWithFrame:CGRectZero + andArgs:nil] retain]); + result(nil); +} + +- (void)handleDispose:(FlutterMethodCall*)call withResult:(FlutterResult)result { + NSDictionary* args = [call arguments]; + long viewId = [args[@"id"] longValue]; + + if (_views[viewId] == nil) { + result([FlutterError errorWithCode:@"unknown_view" + message:@"trying to dispose an unknown" + details:[NSString stringWithFormat:@"view id: '%ld'", viewId]]); + return; + } + + [_views[viewId] dispose]; + _views.erase(viewId); + result(nil); +} + +@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h new file mode 100644 index 0000000000000..7d83093846f15 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -0,0 +1,21 @@ +// Copyright 2018 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ +#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ + +#include "flutter/shell/common/shell.h" +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h" +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" + +@interface FlutterPlatformViewsController : NSObject + +- (instancetype)init:(NSObject*)withMessenger; + +- (void)registerViewFactory:(NSObject*)factory + withId:(NSString*)factoryId; + +@end + +#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index eeab410c37a0a..8089ca8b359fe 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -4,6 +4,7 @@ #define FML_USED_ON_EMBEDDER +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h" #include @@ -53,6 +54,7 @@ @implementation FlutterViewController { fml::scoped_nsobject _flutterView; fml::scoped_nsobject _splashScreenView; fml::ScopedBlock _flutterViewRenderedCallback; + fml::scoped_nsobject _platformViewsController; UIInterfaceOrientationMask _orientationPreferences; UIStatusBarStyle _statusBarStyle; blink::ViewportMetrics _viewportMetrics; @@ -113,6 +115,7 @@ - (void)performCommonViewControllerInitialization { [self setupChannels]; [self setupNotificationCenterObservers]; + _platformViewsController.reset([[FlutterPlatformViewsController alloc] init:self]); _pluginPublications = [NSMutableDictionary new]; } } @@ -1091,6 +1094,12 @@ - (void)onPreferredStatusBarStyleUpdated:(NSNotification*)notification { }); } +#pragma mark - Platform views + +- (FlutterPlatformViewsController*)platformViewsController { + return _platformViewsController.get(); +} + #pragma mark - FlutterBinaryMessenger - (void)sendOnChannel:(NSString*)channel message:(NSData*)message { @@ -1197,6 +1206,11 @@ - (void)dealloc { return _flutterViewController; } +- (void)registerViewFactory:(NSObject*)factory + withId:(NSString*)factoryId { + [[_flutterViewController platformViewsController] registerViewFactory:factory withId:factoryId]; +} + - (void)publish:(NSObject*)value { _flutterViewController.pluginPublications[_pluginKey] = value; } From c8535bb90ab088eb3f4fb9d3b5f22f76aed346e4 Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Wed, 17 Oct 2018 16:49:14 -0700 Subject: [PATCH 2/5] make PlatformViewsController a C++ class --- .../framework/Source/FlutterPlatformViews.mm | 69 +++++++++---------- .../Source/FlutterPlatformViews_Internal.h | 23 +++++-- .../framework/Source/FlutterViewController.mm | 8 +-- 3 files changed, 53 insertions(+), 47 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 8fe2c15b0db04..56d4143dfcba9 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -10,58 +10,42 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" -@implementation FlutterPlatformViewsController { - fml::scoped_nsobject _channel; - std::map>> _factories; - std::map>> _views; -} +namespace shell { -- (instancetype)init:(NSObject*)withMessenger { - if (self = [super init]) { - _channel.reset([[FlutterMethodChannel alloc] - initWithName:@"flutter/platform_views" - binaryMessenger:withMessenger - codec:[FlutterStandardMethodCodec sharedInstance]]); - [_channel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { - [self methodCallHandler:call withResult:result]; - }]; - } - return self; -} - -- (void)registerViewFactory:(NSObject*)factory - withId:(NSString*)factoryId { - std::string idString([factoryId UTF8String]); - NSAssert(_factories.count(idString) == 0, - ([NSString stringWithFormat:@"Can't register an already registered view factory: %@", - factoryId])); - _factories[idString] = - fml::scoped_nsobject>([factory retain]); +FlutterPlatformViewsController::FlutterPlatformViewsController( + NSObject* messenger) { + channel_.reset([[FlutterMethodChannel alloc] + initWithName:@"flutter/platform_views" + binaryMessenger:messenger + codec:[FlutterStandardMethodCodec sharedInstance]]); + [channel_.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { + OnMethodCall(call, result); + }]; } -- (void)methodCallHandler:(FlutterMethodCall*)call withResult:(FlutterResult)result { +void FlutterPlatformViewsController::OnMethodCall(FlutterMethodCall* call, FlutterResult& result) { if ([[call method] isEqualToString:@"create"]) { - [self handleCreate:call withResult:result]; + OnCreate(call, result); } else if ([[call method] isEqualToString:@"dispose"]) { - [self handleDispose:call withResult:result]; + OnDispose(call, result); } else { result(FlutterMethodNotImplemented); } } -- (void)handleCreate:(FlutterMethodCall*)call withResult:(FlutterResult)result { +void FlutterPlatformViewsController::OnCreate(FlutterMethodCall* call, FlutterResult& result) { NSDictionary* args = [call arguments]; long viewId = [args[@"id"] longValue]; std::string viewType([args[@"viewType"] UTF8String]); - if (_views[viewId] != nil) { + if (views_[viewId] != nil) { result([FlutterError errorWithCode:@"recreating_view" message:@"trying to create an already created view" details:[NSString stringWithFormat:@"view id: '%ld'", viewId]]); } - NSObject* factory = _factories[viewType].get(); + NSObject* factory = factories_[viewType].get(); if (factory == nil) { result([FlutterError errorWithCode:@"unregistered_view_type" message:@"trying to create a view with an unregistered type" @@ -71,26 +55,35 @@ - (void)handleCreate:(FlutterMethodCall*)call withResult:(FlutterResult)result { } // TODO(amirh): decode and pass the creation args. - _views[viewId] = + views_[viewId] = fml::scoped_nsobject>([[factory createWithFrame:CGRectZero andArgs:nil] retain]); result(nil); } -- (void)handleDispose:(FlutterMethodCall*)call withResult:(FlutterResult)result { +void FlutterPlatformViewsController::OnDispose(FlutterMethodCall* call, FlutterResult& result) { NSDictionary* args = [call arguments]; long viewId = [args[@"id"] longValue]; - if (_views[viewId] == nil) { + if (views_[viewId] == nil) { result([FlutterError errorWithCode:@"unknown_view" message:@"trying to dispose an unknown" details:[NSString stringWithFormat:@"view id: '%ld'", viewId]]); return; } - [_views[viewId] dispose]; - _views.erase(viewId); + [views_[viewId] dispose]; + views_.erase(viewId); result(nil); } -@end +void FlutterPlatformViewsController::RegisterViewFactory( + NSObject* factory, + NSString* factoryId) { + std::string idString([factoryId UTF8String]); + FML_CHECK(factories_.count(idString) == 0); + factories_[idString] = + fml::scoped_nsobject>([factory retain]); +} + +} // namespace shell diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 7d83093846f15..f13903f8153a9 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -5,17 +5,30 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ +#include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/common/shell.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h" +#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h" -@interface FlutterPlatformViewsController : NSObject +namespace shell { -- (instancetype)init:(NSObject*)withMessenger; +class FlutterPlatformViewsController { + public: + FlutterPlatformViewsController(NSObject* messenger); -- (void)registerViewFactory:(NSObject*)factory - withId:(NSString*)factoryId; + void RegisterViewFactory(NSObject* factory, NSString* factoryId); -@end + private: + fml::scoped_nsobject channel_; + std::map>> factories_; + std::map>> views_; + + void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); + void OnCreate(FlutterMethodCall* call, FlutterResult& result); + void OnDispose(FlutterMethodCall* call, FlutterResult& result); +}; + +} // namespace shell #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 8089ca8b359fe..1575f2a4a8592 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -54,7 +54,7 @@ @implementation FlutterViewController { fml::scoped_nsobject _flutterView; fml::scoped_nsobject _splashScreenView; fml::ScopedBlock _flutterViewRenderedCallback; - fml::scoped_nsobject _platformViewsController; + std::unique_ptr _platformViewsController; UIInterfaceOrientationMask _orientationPreferences; UIStatusBarStyle _statusBarStyle; blink::ViewportMetrics _viewportMetrics; @@ -115,7 +115,7 @@ - (void)performCommonViewControllerInitialization { [self setupChannels]; [self setupNotificationCenterObservers]; - _platformViewsController.reset([[FlutterPlatformViewsController alloc] init:self]); + _platformViewsController.reset(new shell::FlutterPlatformViewsController(self)); _pluginPublications = [NSMutableDictionary new]; } } @@ -1096,7 +1096,7 @@ - (void)onPreferredStatusBarStyleUpdated:(NSNotification*)notification { #pragma mark - Platform views -- (FlutterPlatformViewsController*)platformViewsController { +- (shell::FlutterPlatformViewsController*)platformViewsController { return _platformViewsController.get(); } @@ -1208,7 +1208,7 @@ - (void)dealloc { - (void)registerViewFactory:(NSObject*)factory withId:(NSString*)factoryId { - [[_flutterViewController platformViewsController] registerViewFactory:factory withId:factoryId]; + [_flutterViewController platformViewsController] -> RegisterViewFactory(factory, factoryId); } - (void)publish:(NSObject*)value { From e9551d75e3da4c5faba0fd50bc1ffabfc7edfd40 Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Thu, 18 Oct 2018 08:29:00 -0700 Subject: [PATCH 3/5] review comments followup and expose viewId to the plugin --- .../framework/Headers/FlutterPlatformViews.h | 48 ++++++++++--------- .../ios/framework/Headers/FlutterPlugin.h | 15 +++--- .../framework/Source/FlutterPlatformViews.mm | 5 +- .../Source/FlutterPlatformViews_Internal.h | 2 +- 4 files changed, 36 insertions(+), 34 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h index 33d08152a5512..8b0f05b277559 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h @@ -15,17 +15,17 @@ NS_ASSUME_NONNULL_BEGIN /** - An instance of a `UIView` created by a `FlutterPlatformViewFactory`. - - This protocol is used to associate a view with a dispose callback. + * An instance of a `UIView` created by a `FlutterPlatformViewFactory`. + * + * This protocol is used to associate a view with a dispose callback. */ FLUTTER_EXPORT @protocol FlutterPlatformView - (UIView*)view; /** - Called when the Flutter engine no longer needs this `view`. - - The implementation of this method should release any kept for this view. + * Called when the Flutter engine no longer needs this `view`. + * + * The implementation of this method should release any kept for this view. */ - (void)dispose; @end @@ -33,26 +33,28 @@ FLUTTER_EXPORT FLUTTER_EXPORT @protocol FlutterPlatformViewFactory /** - Create a `FlutterPlatformView`. - - Implemented by iOS code that expose a `UIView` for embedding in a Flutter app. - - The implementation of this method should create a new `UIView` and return a `FlutterPlatformView` - that wraps it. - - - Parameters: - - frame: The rectangle for the newly created `UIView` measued in points. - - args: Parameters for creating the `UIView` sent from the Dart side of the Flutter app. - If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart - code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by - `createArgsCodec`. + * Create a `FlutterPlatformView`. + * + * Implemented by iOS code that expose a `UIView` for embedding in a Flutter app. + * + * The implementation of this method should create a new `UIView` and return a `FlutterPlatformView` + * that wraps it. + * + * @param frame The rectangle for the newly created `UIView` measued in points. + * @param viewId A unique identifier for this `UIView`. + * @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app. + * If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart + * code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by + * `createArgsCodec`. */ -- (NSObject*)createWithFrame:(CGRect)frame andArgs:(id _Nullable)args; +- (NSObject*)createWithFrame:(CGRect)frame + viewId:(int64_t)viewId + andArgs:(id _Nullable)args; /** - Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`. - - Only needs to be implemented if `createWithFrame` needs an arguments parameter. + * Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`. + * + * Only needs to be implemented if `createWithFrame` needs an arguments parameter. */ @optional - (NSObject*)createArgsCodec; diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h index 87cdbd3af28a7..4f6497712b619 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h @@ -205,14 +205,13 @@ NS_ASSUME_NONNULL_BEGIN - (NSObject*)textures; /** - Registers a `FlutterPlatformViewFactory` for creation of platfrom views. - - Plugins expose `UIView` for embedding in Flutter apps by registering a view factory. - - - Parameters: - - factory: The view factory that will be registered. - - factoryId:: A unique identifier for the factory, the Dart code of the Flutter app can use - this identifier to request creation of a `UIView` by the registered factory. + * Registers a `FlutterPlatformViewFactory` for creation of platfrom views. + * + * Plugins expose `UIView` for embedding in Flutter apps by registering a view factory. + * + * @param factory The view factory that will be registered. + * @param factoryId:: A unique identifier for the factory, the Dart code of the Flutter app can use + * this identifier to request creation of a `UIView` by the registered factory. */ - (void)registerViewFactory:(NSObject*)factory withId:(NSString*)factoryId; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 56d4143dfcba9..1c9fe43aaab16 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -57,18 +57,19 @@ // TODO(amirh): decode and pass the creation args. views_[viewId] = fml::scoped_nsobject>([[factory createWithFrame:CGRectZero + viewId:viewId andArgs:nil] retain]); result(nil); } void FlutterPlatformViewsController::OnDispose(FlutterMethodCall* call, FlutterResult& result) { NSDictionary* args = [call arguments]; - long viewId = [args[@"id"] longValue]; + int64_t viewId = [args[@"id"] longLongValue]; if (views_[viewId] == nil) { result([FlutterError errorWithCode:@"unknown_view" message:@"trying to dispose an unknown" - details:[NSString stringWithFormat:@"view id: '%ld'", viewId]]); + details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); return; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index f13903f8153a9..aa1fa1ec20c23 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -22,7 +22,7 @@ class FlutterPlatformViewsController { private: fml::scoped_nsobject channel_; std::map>> factories_; - std::map>> views_; + std::map>> views_; void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); void OnCreate(FlutterMethodCall* call, FlutterResult& result); From f62c939a440654ed6cb67d663a2115da8d089359 Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Tue, 23 Oct 2018 14:44:07 -0700 Subject: [PATCH 4/5] review comments followup --- .../framework/Headers/FlutterPlatformViews.h | 35 +++++-------------- .../framework/Source/FlutterPlatformViews.mm | 8 ++--- .../Source/FlutterPlatformViews_Internal.h | 2 +- 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h index 8b0f05b277559..c077d52cd2a00 100644 --- a/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h +++ b/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h @@ -5,31 +5,13 @@ #ifndef FLUTTER_FLUTTERPLATFORMVIEWS_H_ #define FLUTTER_FLUTTERPLATFORMVIEWS_H_ -#import -#import #import -#include "FlutterCodecs.h" -#include "FlutterMacros.h" +#import "FlutterCodecs.h" +#import "FlutterMacros.h" NS_ASSUME_NONNULL_BEGIN -/** - * An instance of a `UIView` created by a `FlutterPlatformViewFactory`. - * - * This protocol is used to associate a view with a dispose callback. - */ -FLUTTER_EXPORT -@protocol FlutterPlatformView -- (UIView*)view; -/** - * Called when the Flutter engine no longer needs this `view`. - * - * The implementation of this method should release any kept for this view. - */ -- (void)dispose; -@end - FLUTTER_EXPORT @protocol FlutterPlatformViewFactory /** @@ -37,19 +19,18 @@ FLUTTER_EXPORT * * Implemented by iOS code that expose a `UIView` for embedding in a Flutter app. * - * The implementation of this method should create a new `UIView` and return a `FlutterPlatformView` - * that wraps it. + * The implementation of this method should create a new `UIView` and return it. * * @param frame The rectangle for the newly created `UIView` measued in points. - * @param viewId A unique identifier for this `UIView`. - * @param args Parameters for creating the `UIView` sent from the Dart side of the Flutter app. + * @param viewIdentifier A unique identifier for this `UIView`. + * @param arguments Parameters for creating the `UIView` sent from the Dart side of the Flutter app. * If `createArgsCodec` is not implemented, or if no creation arguments were sent from the Dart * code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by * `createArgsCodec`. */ -- (NSObject*)createWithFrame:(CGRect)frame - viewId:(int64_t)viewId - andArgs:(id _Nullable)args; +- (UIView*)createWithFrame:(CGRect)frame + viewIdentifier:(int64_t)viewId + arguments:(id _Nullable)args; /** * Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 1c9fe43aaab16..9da977da8c993 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -55,10 +55,9 @@ } // TODO(amirh): decode and pass the creation args. - views_[viewId] = - fml::scoped_nsobject>([[factory createWithFrame:CGRectZero - viewId:viewId - andArgs:nil] retain]); + views_[viewId] = fml::scoped_nsobject([[factory createWithFrame:CGRectZero + viewIdentifier:viewId + arguments:nil] retain]); result(nil); } @@ -73,7 +72,6 @@ return; } - [views_[viewId] dispose]; views_.erase(viewId); result(nil); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index aa1fa1ec20c23..bdca34e8965a1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -22,7 +22,7 @@ class FlutterPlatformViewsController { private: fml::scoped_nsobject channel_; std::map>> factories_; - std::map>> views_; + std::map> views_; void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); void OnCreate(FlutterMethodCall* call, FlutterResult& result); From 01bce7b5b52766c5b6d213101fef27555bd08edd Mon Sep 17 00:00:00 2001 From: Amir Hardon Date: Wed, 24 Oct 2018 14:58:45 -0700 Subject: [PATCH 5/5] review comments followup --- .../darwin/ios/framework/Source/FlutterPlatformViews_Internal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index bdca34e8965a1..620bec26d3ee5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -27,6 +27,8 @@ class FlutterPlatformViewsController { void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); void OnCreate(FlutterMethodCall* call, FlutterResult& result); void OnDispose(FlutterMethodCall* call, FlutterResult& result); + + FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); }; } // namespace shell