Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "FlutterBinaryMessenger.h"
#import "FlutterDartProject.h"
#import "FlutterEngine.h"
#import "FlutterEngineGroup.h"
#import "FlutterMacros.h"
#import "FlutterPlugin.h"
#import "FlutterTexture.h"
Expand Down Expand Up @@ -68,6 +69,23 @@ FLUTTER_DARWIN_EXPORT
nibName:(nullable NSString*)nibName
bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER;

/**
* Initializes this FlutterViewController with the specified `FlutterEngineGroup`
*
* FlutterViewController will create an new `FlutterEngine` with `options` and use this engine do
* the same thing like initWithEngine:nibName:bundle:, and when this `FlutterViewController`
* pop,the engine will be gone.
*
* @param engineGroup The specified `FlutterEngineGroup` to use to create new `FlutterEngine`.
* @param options The specified options to give FlutterEngineGroup to create new `FlutterEngine`.
* @param nibName The NIB name to initialize this UIViewController with.
* @param nibBundle The NIB bundle.
*/
- (instancetype)initWithEngineGroup:(FlutterEngineGroup*)engineGroup
options:(nullable FlutterEngineGroupOptions*)options
nibName:(nullable NSString*)nibName
bundle:(nullable NSBundle*)nibBundle NS_DESIGNATED_INITIALIZER;

/**
* Initializes a new FlutterViewController and `FlutterEngine` with the specified
* `FlutterDartProject`.
Expand Down
50 changes: 33 additions & 17 deletions shell/platform/darwin/ios/framework/Source/FlutterViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -133,25 +133,21 @@ - (instancetype)initWithEngine:(FlutterEngine*)engine
NSAssert(engine != nil, @"Engine is required");
self = [super initWithNibName:nibName bundle:nibBundle];
if (self) {
_viewOpaque = YES;
if (engine.viewController) {
FML_LOG(ERROR) << "The supplied FlutterEngine " << [[engine description] UTF8String]
<< " is already used with FlutterViewController instance "
<< [[engine.viewController description] UTF8String]
<< ". One instance of the FlutterEngine can only be attached to one "
"FlutterViewController at a time. Set FlutterEngine.viewController "
"to nil before attaching it to another FlutterViewController.";
}
_engine.reset([engine retain]);
_engineNeedsLaunch = NO;
_flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]);
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterViewController>>(self);
_ongoingTouches.reset([[NSMutableSet alloc] init]);

[self performCommonViewControllerInitialization];
[engine setViewController:self];
[self setupEngine:engine];
}
return self;
}

- (instancetype)initWithEngineGroup:(FlutterEngineGroup*)engineGroup
options:(nullable FlutterEngineGroupOptions*)options
nibName:(nullable NSString*)nibName
bundle:(nullable NSBundle*)nibBundle {
NSAssert(engineGroup != nil, @"FlutterEngineGroup is required");
self = [super initWithNibName:nibName bundle:nibBundle];
if (self) {
FlutterEngine* engine = [engineGroup makeEngineWithOptions:options];
[self setupEngine:engine];
}
return self;
}

Expand Down Expand Up @@ -198,6 +194,26 @@ - (instancetype)init {
return [self initWithProject:nil nibName:nil bundle:nil];
}

- (void)setupEngine:(FlutterEngine*)engine {
_viewOpaque = YES;
if (engine.viewController) {
FML_LOG(ERROR) << "The supplied FlutterEngine " << [[engine description] UTF8String]
<< " is already used with FlutterViewController instance "
<< [[engine.viewController description] UTF8String]
<< ". One instance of the FlutterEngine can only be attached to one "
"FlutterViewController at a time. Set FlutterEngine.viewController "
"to nil before attaching it to another FlutterViewController.";
}
_engine.reset([engine retain]);
_engineNeedsLaunch = NO;
_flutterView.reset([[FlutterView alloc] initWithDelegate:_engine opaque:self.isViewOpaque]);
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterViewController>>(self);
_ongoingTouches.reset([[NSMutableSet alloc] init]);

[self performCommonViewControllerInitialization];
[engine setViewController:self];
}

- (void)sharedSetupWithProject:(nullable FlutterDartProject*)project
initialRoute:(nullable NSString*)initialRoute {
// Need the project to get settings for the view. Initializing it here means
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@ @interface FlutterEngine (TestLowMemory)
- (void)notifyLowMemory;
@end

@interface FlutterEngineGroup ()
@property(nonatomic, strong) NSMutableArray<FlutterEngine*>* engines;
- (FlutterEngine*)makeEngineWithOptions:(nullable FlutterEngineGroupOptions*)options;
@end

extern NSNotificationName const FlutterViewControllerWillDealloc;

/// A simple mock class for FlutterEngine.
Expand Down Expand Up @@ -155,6 +160,19 @@ - (void)tearDown {
self.messageSent = nil;
}

- (void)testViewControllerInitWithEngineGroupWithEngineGroupOptions {
FlutterEngineGroup* engineGroup =
OCMPartialMock([[FlutterEngineGroup alloc] initWithName:@"io.flutter" project:nil]);
FlutterEngineGroupOptions* options = [[FlutterEngineGroupOptions alloc] init];

FlutterViewController* controller = [[FlutterViewController alloc] initWithEngineGroup:engineGroup
options:options
nibName:nil
bundle:nil];
OCMStub([[engineGroup engines] firstObject]).andReturn(controller.engine);
OCMVerify([engineGroup makeEngineWithOptions:options]);
}

- (void)testkeyboardWillChangeFrameWillStartKeyboardAnimation {
FlutterEngine* mockEngine = OCMPartialMock([[FlutterEngine alloc] init]);
[mockEngine createShell:@"" libraryURI:@"" initialRoute:nil];
Expand Down