Reverts "[Reland] Implements UISceneDelegate dynamically w/ FlutterLaunchEngine (#168396) (#168914)" (#169250)

<!-- start_original_pr_link -->
Reverts: flutter/flutter#168914
<!-- end_original_pr_link -->
<!-- start_initiating_author -->
Initiated by: gaaclarke
<!-- end_initiating_author -->
<!-- start_revert_reason -->
Reason for reverting:
https://ci.chromium.org/ui/p/flutter/builders/prod/Mac_ios%20external_ui_integration_test_ios/16792/overview

The external texture integration test is failing. Running the host app
appeared to work but one of the driver asserts isn't working.
<!-- end_revert_reason -->
<!-- start_original_pr_author -->
Original PR Author: gaaclarke
<!-- end_original_pr_author -->

<!-- start_reviewers -->
Reviewed By: {vashworth}
<!-- end_reviewers -->

<!-- start_revert_body -->
This change reverts the following previous change:
## **BREAKING CHANGE**

Adopting Apple's UISceneDelegate protocol shifts the initialization
order of apps. For the common cases we've made sure they will work
without change. The one case that will require a change is any app that
in `-[UIApplicateDelegate didFinishLaunchingWithOptions:]` assumes that
`UIApplicationDelegate.window.rootViewController` is a
`FlutterViewController` instance. This is sometimes done to register
platform channels directly on the `FlutterViewController`. Instead users
should use the `FlutterPluginRegistry` API's to create platform channels
in `-[UIApplicateDelegate didFinishLaunchingWithOptions:]`, like
`FlutterPlugin`s do.

An example can be seen here:
https://github.com/flutter/flutter/pull/168914/files#diff-9f59c5248b58124beca7e290a57646023cda3ca024607092c6c6932606ce16ee

## Changes since revert
Device lab tests have been migrated to using the FlutterPlugin API for
creating platform channels at process launch.

## Description
fixes: https://github.com/flutter/flutter/issues/167267

design doc:

https://docs.google.com/document/d/1ZfcQOs-UKRa9jsFG84-MTFeibZTLKCvPQLxF2eskx44/edit?tab=t.0

relands https://github.com/flutter/flutter/pull/168396

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

<!-- end_revert_body -->

Co-authored-by: auto-submit[bot] <flutter-engprod-team@google.com>
This commit is contained in:
auto-submit[bot] 2025-05-22 03:32:21 +00:00 committed by GitHub
parent 3fb1899377
commit 88d184dada
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 35 additions and 395 deletions

View File

@ -86,36 +86,38 @@ const UInt8 PAIR = 129;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
id<FlutterPluginRegistrar> registrar = [self registrarForPlugin:@"platform-channel-test"];
FlutterViewController *flutterController =
(FlutterViewController *)self.window.rootViewController;
ExtendedReaderWriter* extendedReaderWriter = [ExtendedReaderWriter new];
[self setupMessagingHandshakeOnChannel:
[FlutterBasicMessageChannel messageChannelWithName:@"binary-msg"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterBinaryCodec sharedInstance]]];
[self setupMessagingHandshakeOnChannel:
[FlutterBasicMessageChannel messageChannelWithName:@"string-msg"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterStringCodec sharedInstance]]];
[self setupMessagingHandshakeOnChannel:
[FlutterBasicMessageChannel messageChannelWithName:@"json-msg"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterJSONMessageCodec sharedInstance]]];
[self setupMessagingHandshakeOnChannel:
[FlutterBasicMessageChannel messageChannelWithName:@"std-msg"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterStandardMessageCodec codecWithReaderWriter:extendedReaderWriter]]];
[self setupMethodCallSuccessHandshakeOnChannel:
[FlutterMethodChannel methodChannelWithName:@"json-method"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterJSONMethodCodec sharedInstance]]];
[self setupMethodCallSuccessHandshakeOnChannel:
[FlutterMethodChannel methodChannelWithName:@"std-method"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterStandardMethodCodec codecWithReaderWriter:extendedReaderWriter]]];
[[FlutterBasicMessageChannel
messageChannelWithName:@"std-echo"
binaryMessenger:registrar.messenger
binaryMessenger:flutterController
codec:[FlutterStandardMessageCodec
codecWithReaderWriter:extendedReaderWriter]]
setMessageHandler:^(id message, FlutterReply reply) {

View File

@ -21,15 +21,13 @@
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
id<FlutterPluginRegistrar> registrar = [self registrarForPlugin:@"external_texture_test"];
FlutterViewController* flutterController =
(FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* channel =
[FlutterMethodChannel methodChannelWithName:@"texture"
binaryMessenger:registrar.messenger];
binaryMessenger:flutterController];
[channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
if ([@"start" isEqualToString:call.method]) {
FlutterViewController* flutterController =
(FlutterViewController*)self.window.rootViewController;
_textureId = [flutterController registerTexture:self];
_framesProduced = 0;
_framesConsumed = 0;
_frameRate = 1.0 / [(NSNumber*) call.arguments intValue];
@ -52,7 +50,7 @@
result(FlutterMethodNotImplemented);
}
}];
_textureId = [flutterController registerTexture:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

View File

@ -52778,7 +52778,6 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/ConnectionCo
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FakeUIPressProxy.swift + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Test.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache_Internal.h + ../../../flutter/LICENSE
@ -52809,9 +52808,6 @@ ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySe
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManagerTest.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.m + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngineTest.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayerTest.mm + ../../../flutter/LICENSE
@ -55808,7 +55804,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/ConnectionColl
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FakeUIPressProxy.swift
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegateTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Test.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache_Internal.h
@ -55839,9 +55834,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeySeco
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManagerTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.m
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngineTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayer.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterMetalLayerTest.mm

View File

@ -425,37 +425,6 @@
"ios_debug_unopt"
]
},
{
"type": "shell",
"command": "./flutter/bin/et",
"options": {
"cwd": "${workspaceFolder}/.."
},
"problemMatcher": [
"$gcc"
],
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"clear": true
},
"group": {
"kind": "build"
},
"label": "ios_debug_sim_unopt_arm64",
"args": [
"build",
"-c",
"host_debug_unopt_arm64",
"&&",
"./flutter/bin/et",
"build",
"-c",
"ios_debug_sim_unopt_arm64"
]
},
{
"type": "shell",
"command": "./flutter/bin/et",

View File

@ -75,7 +75,6 @@ source_set("flutter_framework_source") {
sources = [
"framework/Source/FlutterAppDelegate.mm",
"framework/Source/FlutterAppDelegate_Internal.h",
"framework/Source/FlutterCallbackCache.mm",
"framework/Source/FlutterCallbackCache_Internal.h",
"framework/Source/FlutterChannelKeyResponder.h",
@ -94,8 +93,6 @@ source_set("flutter_framework_source") {
"framework/Source/FlutterKeySecondaryResponder.h",
"framework/Source/FlutterKeyboardManager.h",
"framework/Source/FlutterKeyboardManager.mm",
"framework/Source/FlutterLaunchEngine.h",
"framework/Source/FlutterLaunchEngine.m",
"framework/Source/FlutterMetalLayer.h",
"framework/Source/FlutterMetalLayer.mm",
"framework/Source/FlutterOverlayView.h",
@ -253,7 +250,6 @@ if (enable_ios_unittests) {
"framework/Source/FlutterFakeKeyEvents.h",
"framework/Source/FlutterFakeKeyEvents.mm",
"framework/Source/FlutterKeyboardManagerTest.mm",
"framework/Source/FlutterLaunchEngineTest.mm",
"framework/Source/FlutterMetalLayerTest.mm",
"framework/Source/FlutterPlatformPluginTest.mm",
"framework/Source/FlutterPlatformViewsTest.mm",

View File

@ -9,7 +9,6 @@
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Test.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate_internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSharedApplication.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
@ -21,33 +20,9 @@ static NSString* const kRemoteNotificationCapabitiliy = @"remote-notification";
static NSString* const kBackgroundFetchCapatibility = @"fetch";
static NSString* const kRestorationStateAppModificationKey = @"mod-date";
@interface FlutterSceneDelegate : NSObject <UIWindowSceneDelegate>
@property(nonatomic, strong, nullable) UIWindow* window;
@end
@implementation FlutterSceneDelegate
- (void)scene:(UIScene*)scene
willConnectToSession:(UISceneSession*)session
options:(UISceneConnectionOptions*)connectionOptions {
NSObject<UIApplicationDelegate>* appDelegate = FlutterSharedApplication.application.delegate;
if (appDelegate.window.rootViewController) {
// If this is not nil we are running into a case where someone is manually
// performing root view controller setup in the UIApplicationDelegate.
UIWindowScene* windowScene = (UIWindowScene*)scene;
self.window = [[UIWindow alloc] initWithWindowScene:windowScene];
self.window.rootViewController = appDelegate.window.rootViewController;
appDelegate.window = self.window;
[self.window makeKeyAndVisible];
}
}
@end
@interface FlutterAppDelegate ()
@property(nonatomic, copy) FlutterViewController* (^rootFlutterViewControllerGetter)(void);
@property(nonatomic, strong) FlutterPluginAppLifeCycleDelegate* lifeCycleDelegate;
@property(nonatomic, strong) FlutterLaunchEngine* launchEngine;
@end
@implementation FlutterAppDelegate
@ -55,15 +30,10 @@ static NSString* const kRestorationStateAppModificationKey = @"mod-date";
- (instancetype)init {
if (self = [super init]) {
_lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init];
_launchEngine = [[FlutterLaunchEngine alloc] init];
}
return self;
}
- (nullable FlutterEngine*)takeLaunchEngine {
return [self.launchEngine takeEngine];
}
- (BOOL)application:(UIApplication*)application
willFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
return [self.lifeCycleDelegate application:application
@ -263,7 +233,7 @@ static NSString* const kRestorationStateAppModificationKey = @"mod-date";
if (flutterRootViewController) {
return [[flutterRootViewController pluginRegistry] registrarForPlugin:pluginKey];
}
return [self.launchEngine.engine registrarForPlugin:pluginKey];
return nil;
}
- (BOOL)hasPlugin:(NSString*)pluginKey {
@ -271,7 +241,7 @@ static NSString* const kRestorationStateAppModificationKey = @"mod-date";
if (flutterRootViewController) {
return [[flutterRootViewController pluginRegistry] hasPlugin:pluginKey];
}
return [self.launchEngine.engine hasPlugin:pluginKey];
return false;
}
- (NSObject*)valuePublishedByPlugin:(NSString*)pluginKey {
@ -279,7 +249,7 @@ static NSString* const kRestorationStateAppModificationKey = @"mod-date";
if (flutterRootViewController) {
return [[flutterRootViewController pluginRegistry] valuePublishedByPlugin:pluginKey];
}
return [self.launchEngine.engine valuePublishedByPlugin:pluginKey];
return nil;
}
#pragma mark - Selectors handling
@ -371,31 +341,4 @@ static NSString* const kRestorationStateAppModificationKey = @"mod-date";
return [fileDate timeIntervalSince1970];
}
- (UISceneConfiguration*)application:(UIApplication*)application
configurationForConnectingSceneSession:(UISceneSession*)connectingSceneSession
options:(UISceneConnectionOptions*)options {
NSDictionary* sceneManifest =
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIApplicationSceneManifest"];
NSDictionary* sceneConfigs = sceneManifest[@"UISceneConfigurations"];
if (sceneConfigs.count > 0) {
return connectingSceneSession.configuration;
} else {
UISceneConfiguration* config =
[UISceneConfiguration configurationWithName:@"flutter"
sessionRole:connectingSceneSession.role];
config.delegateClass = [FlutterSceneDelegate class];
NSString* mainStoryboard =
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIMainStoryboardFile"];
if (mainStoryboard) {
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:mainStoryboard
bundle:[NSBundle mainBundle]];
config.storyboard = storyboard;
}
return config;
}
}
@end

View File

@ -8,7 +8,6 @@
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h"
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h"
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Test.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Test.h"
@ -155,20 +154,6 @@ FLUTTER_ASSERT_ARC
XCTAssertNil(weakWindow);
}
- (void)testGrabLaunchEngine {
// Clear out the mocking of the root view controller.
[self.mockMainBundle stopMocking];
self.appDelegate.rootFlutterViewControllerGetter = nil;
// Working with plugins forces the creation of an engine.
XCTAssertFalse([self.appDelegate hasPlugin:@"hello"]);
XCTAssertNotNil([self.appDelegate takeLaunchEngine]);
XCTAssertNil([self.appDelegate takeLaunchEngine]);
}
- (void)testGrabLaunchEngineWithoutPlugins {
XCTAssertNil([self.appDelegate takeLaunchEngine]);
}
#pragma mark - Deep linking
- (void)testUniversalLinkPushRouteInformation {

View File

@ -1,16 +0,0 @@
// Copyright 2013 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_FLUTTERAPPDELEGATE_INTERNAL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERAPPDELEGATE_INTERNAL_H_
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterAppDelegate.h"
@interface FlutterAppDelegate ()
- (nullable FlutterEngine*)takeLaunchEngine;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERAPPDELEGATE_INTERNAL_H_

View File

@ -1,40 +0,0 @@
// Copyright 2013 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_FLUTTERLAUNCHENGINE_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERLAUNCHENGINE_H_
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h"
/**
* A lazy container for an engine that will only dispense one engine.
*
* This is used to hold an engine for plugin registration when the
* GeneratedPluginRegistrant is called on a FlutterAppDelegate before the first
* FlutterViewController is set up. This is the typical flow after the
* UISceneDelegate migration.
*
* The launch engine is intended to work only with first FlutterViewController
* instantiated with a NIB since that is the only FlutterEngine that registers
* plugins through the FlutterAppDelegate.
*/
@interface FlutterLaunchEngine : NSObject
/**
* Accessor for the launch engine.
*
* Getting this may allocate an engine.
*/
@property(nonatomic, strong, nullable, readonly) FlutterEngine* engine;
/**
* Take ownership of the launch engine.
*
* After this is called `self.engine` and `takeEngine` will always return nil.
*/
- (nullable FlutterEngine*)takeEngine;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERLAUNCHENGINE_H_

View File

@ -1,52 +0,0 @@
// Copyright 2013 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.
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.h"
@interface FlutterLaunchEngine () {
BOOL _didTakeEngine;
FlutterEngine* _engine;
}
@end
@implementation FlutterLaunchEngine
- (instancetype)init {
self = [super init];
if (self) {
self->_didTakeEngine = NO;
}
return self;
}
- (FlutterEngine*)engine {
if (!_didTakeEngine && !_engine) {
// `allowHeadlessExecution` is set to `YES` since that has always been the
// default behavior. Technically, someone could have set it to `NO` in their
// nib and it would be ignored here. There is no documented usage of this
// though.
// `restorationEnabled` is set to `YES` since a FlutterViewController
// without restoration will have a nil restorationIdentifier leading no
// restoration data being saved. So, it is safe to turn this on in the event
// that someone does not want it.
_engine = [[FlutterEngine alloc] initWithName:@"io.flutter"
project:[[FlutterDartProject alloc] init]
allowHeadlessExecution:YES
restorationEnabled:YES];
// Run engine with default values like initialRoute. Specifying these in
// the FlutterViewController was not supported so it's safe to use the
// defaults.
[_engine run];
}
return _engine;
}
- (nullable FlutterEngine*)takeEngine {
FlutterEngine* result = _engine;
_engine = nil;
_didTakeEngine = YES;
return result;
}
@end

View File

@ -1,26 +0,0 @@
// Copyright 2013 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.
#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.h"
FLUTTER_ASSERT_ARC;
@interface FlutterLaunchEngineTest : XCTestCase
@end
@implementation FlutterLaunchEngineTest
- (void)testSimple {
FlutterLaunchEngine* launchEngine = [[FlutterLaunchEngine alloc] init];
XCTAssertTrue(launchEngine.engine);
XCTAssertTrue([launchEngine takeEngine]);
XCTAssertFalse(launchEngine.engine);
}
@end

View File

@ -17,13 +17,11 @@
#include "flutter/shell/common/thread_host.h"
#import "flutter/shell/platform/darwin/common/InternalFlutterSwiftCommon/InternalFlutterSwiftCommon.h"
#import "flutter/shell/platform/darwin/common/framework/Source/FlutterBinaryMessengerRelay.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterChannelKeyResponder.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyPrimaryResponder.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterKeyboardManager.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterLaunchEngine.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterSharedApplication.h"
@ -257,33 +255,15 @@ typedef struct MouseState {
- (void)sharedSetupWithProject:(nullable FlutterDartProject*)project
initialRoute:(nullable NSString*)initialRoute {
id appDelegate = FlutterSharedApplication.application.delegate;
FlutterEngine* engine;
if ([appDelegate respondsToSelector:@selector(takeLaunchEngine)]) {
if (self.nibName) {
// Only grab the launch engine if it was created with a nib.
// FlutterViewControllers created from nibs can't specify their initial
// routes so it's safe to take it.
engine = [appDelegate takeLaunchEngine];
} else {
// If we registered plugins with a FlutterAppDelegate without a xib, throw
// away the engine that was registered through the FlutterAppDelegate.
// That's not a valid usage of the API.
[appDelegate takeLaunchEngine];
}
}
if (!engine) {
// Need the project to get settings for the view. Initializing it here means
// the Engine class won't initialize it later.
if (!project) {
project = [[FlutterDartProject alloc] init];
}
engine = [[FlutterEngine alloc] initWithName:@"io.flutter"
project:project
allowHeadlessExecution:self.engineAllowHeadlessExecution
restorationEnabled:self.restorationIdentifier != nil];
// Need the project to get settings for the view. Initializing it here means
// the Engine class won't initialize it later.
if (!project) {
project = [[FlutterDartProject alloc] init];
}
FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"io.flutter"
project:project
allowHeadlessExecution:self.engineAllowHeadlessExecution
restorationEnabled:self.restorationIdentifier != nil];
if (!engine) {
return;
}
@ -292,7 +272,7 @@ typedef struct MouseState {
_engine = engine;
_flutterView = [[FlutterView alloc] initWithDelegate:_engine
opaque:_viewOpaque
enableWideGamut:engine.project.isWideGamutEnabled];
enableWideGamut:project.isWideGamutEnabled];
[_engine createShell:nil libraryURI:nil initialRoute:initialRoute];
_engineNeedsLaunch = YES;
_ongoingTouches = [[NSMutableSet alloc] init];

View File

@ -13,7 +13,6 @@
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterHourFormat.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterFakeKeyEvents.h"
@ -119,10 +118,6 @@ extern NSNotificationName const FlutterViewControllerWillDealloc;
@property(nonatomic, copy, readonly) FlutterSendKeyEvent sendEvent;
@end
@interface NSObject (Tests)
@property(nonatomic, strong) FlutterEngine* mockLaunchEngine;
@end
@interface FlutterViewController (Tests)
@property(nonatomic, assign) double targetViewInsetBottom;
@ -2476,28 +2471,4 @@ extern NSNotificationName const FlutterViewControllerWillDealloc;
[mockVC stopMocking];
}
- (void)testGrabLaunchEngine {
id appDelegate = [[UIApplication sharedApplication] delegate];
XCTAssertTrue([appDelegate respondsToSelector:@selector(setMockLaunchEngine:)]);
[appDelegate setMockLaunchEngine:self.mockEngine];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:@"Flutter" bundle:nil];
XCTAssertTrue(storyboard);
FlutterViewController* viewController =
(FlutterViewController*)[storyboard instantiateInitialViewController];
XCTAssertTrue(viewController);
XCTAssertTrue([viewController isKindOfClass:[FlutterViewController class]]);
XCTAssertEqual(viewController.engine, self.mockEngine);
[appDelegate setMockLaunchEngine:nil];
}
- (void)testDoesntGrabLaunchEngine {
id appDelegate = [[UIApplication sharedApplication] delegate];
XCTAssertTrue([appDelegate respondsToSelector:@selector(setMockLaunchEngine:)]);
[appDelegate setMockLaunchEngine:self.mockEngine];
FlutterViewController* flutterViewController = [[FlutterViewController alloc] init];
XCTAssertNotNil(flutterViewController.engine);
XCTAssertNotEqual(flutterViewController.engine, self.mockEngine);
[appDelegate setMockLaunchEngine:nil];
}
@end

View File

@ -7,15 +7,9 @@
#import <UIKit/UIKit.h>
@class FlutterEngine;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property(strong, nonatomic) UIWindow* window;
/** The FlutterEngine that will be served by `takeLaunchEngine`. */
@property(strong, nonatomic) FlutterEngine* mockLaunchEngine;
- (FlutterEngine*)takeLaunchEngine;
@end

View File

@ -30,9 +30,4 @@
- (void)applicationWillTerminate:(UIApplication*)application {
}
- (FlutterEngine*)takeLaunchEngine {
// This is just served up for tests and doesn't actually take ownership.
return _mockLaunchEngine;
}
@end

View File

@ -1,33 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Y6W-OH-hqX">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="s0d-6b-0kx">
<objects>
<viewController id="Y6W-OH-hqX" customClass="FlutterViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="5EZ-qb-Rvc">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vDu-zF-Fre"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Ief-a0-LHa" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="132" y="-27"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View File

@ -8,8 +8,6 @@
/* Begin PBXBuildFile section */
0D1CE5D8233430F400E5D880 /* FlutterChannelsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D1CE5D7233430F400E5D880 /* FlutterChannelsTest.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
0D48E9ED2DCE7B16005474A1 /* Flutter.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D48E9EC2DCE7B16005474A1 /* Flutter.storyboard */; };
0D48E9EE2DCE7B16005474A1 /* Flutter.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D48E9EC2DCE7B16005474A1 /* Flutter.storyboard */; };
0D6AB6B622BB05E100EEE540 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6AB6B522BB05E100EEE540 /* AppDelegate.m */; };
0D6AB6B922BB05E100EEE540 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6AB6B822BB05E100EEE540 /* ViewController.m */; };
0D6AB6BC22BB05E100EEE540 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D6AB6BA22BB05E100EEE540 /* Main.storyboard */; };
@ -57,7 +55,6 @@
0AC2331924BA71D300A85907 /* FlutterPluginAppLifeCycleDelegateTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterPluginAppLifeCycleDelegateTest.mm; sourceTree = "<group>"; };
0AC2332124BA71D300A85907 /* FlutterViewControllerTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterViewControllerTest.mm; sourceTree = "<group>"; };
0D1CE5D7233430F400E5D880 /* FlutterChannelsTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FlutterChannelsTest.m; sourceTree = "<group>"; };
0D48E9EC2DCE7B16005474A1 /* Flutter.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Flutter.storyboard; sourceTree = "<group>"; };
0D6AB6B122BB05E100EEE540 /* IosUnitTests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = IosUnitTests.app; sourceTree = BUILT_PRODUCTS_DIR; };
0D6AB6B422BB05E100EEE540 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
0D6AB6B522BB05E100EEE540 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@ -165,7 +162,6 @@
0D6AB6BF22BB05E200EEE540 /* LaunchScreen.storyboard */,
0D6AB6C222BB05E200EEE540 /* Info.plist */,
0D6AB6C322BB05E200EEE540 /* main.m */,
0D48E9EC2DCE7B16005474A1 /* Flutter.storyboard */,
);
path = App;
sourceTree = "<group>";
@ -274,7 +270,6 @@
0D6AB6C122BB05E200EEE540 /* LaunchScreen.storyboard in Resources */,
0D6AB6BE22BB05E200EEE540 /* Assets.xcassets in Resources */,
0D6AB6BC22BB05E100EEE540 /* Main.storyboard in Resources */,
0D48E9ED2DCE7B16005474A1 /* Flutter.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -282,7 +277,6 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D48E9EE2DCE7B16005474A1 /* Flutter.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -118,10 +118,6 @@ settings:
'*.ipp': cpp
csetjmp: cpp
cfenv: cpp
execution: cpp
print: cpp
source_location: cpp
syncstream: cpp
C_Cpp.default.includePath:
- ${default}
- ${workspaceFolder}/..
@ -256,17 +252,6 @@ tasks:
- build
- -c
- ios_debug_unopt
- <<: *et-task
label: ios_debug_sim_unopt_arm64
args:
- build
- -c
- host_debug_unopt_arm64
- "&&"
- *et-cmd
- build
- -c
- ios_debug_sim_unopt_arm64
- <<: *et-task
label: android_debug_unopt_arm64
args:

View File

@ -13,11 +13,12 @@
- (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
NSObject<FlutterPluginRegistrar>* registrar = [self registrarForPlugin:@"battery"];
FlutterViewController* controller =
(FlutterViewController*)self.window.rootViewController;
FlutterMethodChannel* batteryChannel = [FlutterMethodChannel
methodChannelWithName:@"samples.flutter.io/battery"
binaryMessenger:registrar.messenger];
binaryMessenger:controller];
__weak typeof(self) weakSelf = self;
[batteryChannel setMethodCallHandler:^(FlutterMethodCall* call,
FlutterResult result) {
@ -37,7 +38,7 @@
FlutterEventChannel* chargingChannel = [FlutterEventChannel
eventChannelWithName:@"samples.flutter.io/charging"
binaryMessenger:registrar.messenger];
binaryMessenger:controller];
[chargingChannel setStreamHandler:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

View File

@ -27,9 +27,11 @@ enum MyFlutterErrorCode {
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
GeneratedPluginRegistrant.register(with: self)
let registry = self.registrar(forPlugin: "battery")
guard let controller = window?.rootViewController as? FlutterViewController else {
fatalError("rootViewController is not type FlutterViewController")
}
let batteryChannel = FlutterMethodChannel(name: ChannelName.battery,
binaryMessenger: registry!.messenger())
binaryMessenger: controller.binaryMessenger)
batteryChannel.setMethodCallHandler({
[weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in
guard call.method == "getBatteryLevel" else {
@ -40,7 +42,7 @@ enum MyFlutterErrorCode {
})
let chargingChannel = FlutterEventChannel(name: ChannelName.charging,
binaryMessenger: registry!.messenger())
binaryMessenger: controller.binaryMessenger)
chargingChannel.setStreamHandler(self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}