mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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:
parent
3fb1899377
commit
88d184dada
@ -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) {
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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_
|
@ -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_
|
@ -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
|
@ -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
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
@ -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;
|
||||
};
|
||||
|
@ -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:
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user