未验证 提交 50a8e736 编写于 作者: G gaaclarke 提交者: GitHub

Has a binary messenger (#9419)

Made the engine and the view controllers have BinaryMessengers, not be
BinaryMessengers.  This allows us to break retain cycles and makes the
leaking channels we have not less dire.
上级 7483665e
......@@ -681,6 +681,9 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewCo
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Info.plist
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterAppDelegate_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelayTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm
......
......@@ -44,6 +44,7 @@ shared_library("create_flutter_framework_dylib") {
sources = [
"framework/Source/FlutterAppDelegate.mm",
"framework/Source/FlutterAppDelegate_Internal.h",
"framework/Source/FlutterBinaryMessengerRelay.mm",
"framework/Source/FlutterCallbackCache.mm",
"framework/Source/FlutterCallbackCache_Internal.h",
"framework/Source/FlutterDartProject.mm",
......
......@@ -38,8 +38,7 @@
* One of these methods must be invoked before calling `-setViewController:`.
*/
FLUTTER_EXPORT
@interface FlutterEngine
: NSObject <FlutterBinaryMessenger, FlutterTextureRegistry, FlutterPluginRegistry>
@interface FlutterEngine : NSObject <FlutterTextureRegistry, FlutterPluginRegistry>
/**
* Initialize this FlutterEngine with a `FlutterDartProject`.
*
......@@ -237,6 +236,12 @@ FLUTTER_EXPORT
*/
@property(nonatomic, readonly) NSURL* observatoryUrl;
/**
* The `FlutterBinaryMessenger` associated with this FlutterEngine (used for communicating with
* channels).
*/
@property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger;
@end
#endif // FLUTTER_FLUTTERENGINE_H_
......@@ -41,8 +41,7 @@ extern NSNotificationName const FlutterSemanticsUpdateNotification;
* forth between a FlutterViewController and other `UIViewController`s.
*/
FLUTTER_EXPORT
@interface FlutterViewController
: UIViewController <FlutterBinaryMessenger, FlutterTextureRegistry, FlutterPluginRegistry>
@interface FlutterViewController : UIViewController <FlutterTextureRegistry, FlutterPluginRegistry>
/**
* Initializes this FlutterViewController with the specified `FlutterEngine`.
......@@ -165,6 +164,16 @@ FLUTTER_EXPORT
*/
@property(weak, nonatomic, readonly) FlutterEngine* engine;
/**
* The `FlutterBinaryMessenger` associated with this FlutterViewController (used for communicating
* with channels).
*
* @deprecated Since |FlutterViewController| just forwards binary messenger calls to the
* |FlutterEngine|, just use the FlutterEngine.binaryMessenger.
*/
@property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* binaryMessenger
__attribute__((deprecated));
@end
#endif // FLUTTER_FLUTTERVIEWCONTROLLER_H_
// 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/common/framework/Headers/FlutterBinaryMessenger.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
#ifndef NDEBUG
FLUTTER_EXPORT
#endif
@interface FlutterBinaryMessengerRelay : NSObject <FlutterBinaryMessenger>
@property(nonatomic, assign) NSObject<FlutterBinaryMessenger>* parent;
- (instancetype)initWithParent:(NSObject<FlutterBinaryMessenger>*)parent;
@end
// 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/FlutterBinaryMessengerRelay.h"
#include "flutter/fml/logging.h"
@implementation FlutterBinaryMessengerRelay
#pragma mark - FlutterBinaryMessenger
- (instancetype)initWithParent:(NSObject<FlutterBinaryMessenger>*)parent {
self = [super init];
if (self != nil) {
self.parent = parent;
}
return self;
}
- (void)sendOnChannel:(NSString*)channel message:(NSData*)message {
if (self.parent) {
[self.parent sendOnChannel:channel message:message binaryReply:nil];
} else {
FML_LOG(WARNING) << "Communicating on a dead channel.";
}
}
- (void)sendOnChannel:(NSString*)channel
message:(NSData*)message
binaryReply:(FlutterBinaryReply)callback {
if (self.parent) {
[self.parent sendOnChannel:channel message:message binaryReply:callback];
} else {
FML_LOG(WARNING) << "Communicating on a dead channel.";
}
}
- (void)setMessageHandlerOnChannel:(NSString*)channel
binaryMessageHandler:(FlutterBinaryMessageHandler)handler {
if (self.parent) {
[self.parent setMessageHandlerOnChannel:channel binaryMessageHandler:handler];
} else {
FML_LOG(WARNING) << "Communicating on a dead channel.";
}
}
@end
// 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 <OCMock/OCMock.h>
#import <XCTest/XCTest.h>
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h"
#ifndef __has_feature
#define __has_feature(x) 0 /* for non-clang compilers */
#endif
#if !__has_feature(objc_arc)
#error ARC must be enabled!
#endif
@interface FlutterBinaryMessengerRelayTest : XCTestCase
@end
@implementation FlutterBinaryMessengerRelayTest
- (void)setUp {
}
- (void)tearDown {
}
- (void)testCreate {
id messenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
FlutterBinaryMessengerRelay* relay =
[[FlutterBinaryMessengerRelay alloc] initWithParent:messenger];
XCTAssertNotNil(relay);
XCTAssertEqual(messenger, relay.parent);
}
- (void)testPassesCallOn {
id messenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
FlutterBinaryMessengerRelay* relay =
[[FlutterBinaryMessengerRelay alloc] initWithParent:messenger];
char messageData[] = {'a', 'a', 'r', 'o', 'n'};
NSData* message = [NSData dataWithBytes:messageData length:sizeof(messageData)];
NSString* channel = @"foobar";
[relay sendOnChannel:channel message:message binaryReply:nil];
OCMVerify([messenger sendOnChannel:channel message:message binaryReply:nil]);
}
- (void)testDoesntPassCallOn {
id messenger = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
FlutterBinaryMessengerRelay* relay =
[[FlutterBinaryMessengerRelay alloc] initWithParent:messenger];
char messageData[] = {'a', 'a', 'r', 'o', 'n'};
NSData* message = [NSData dataWithBytes:messageData length:sizeof(messageData)];
NSString* channel = @"foobar";
relay.parent = nil;
[relay sendOnChannel:channel message:message binaryReply:nil];
}
@end
......@@ -17,16 +17,17 @@
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/platform/darwin/common/command_line.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
@interface FlutterEngine () <FlutterTextInputDelegate>
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
@interface FlutterEngine () <FlutterTextInputDelegate, FlutterBinaryMessenger>
// Maintains a dictionary of plugin names that have registered with the engine. Used by
// FlutterEngineRegistrar to implement a FlutterPluginRegistrar.
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
......@@ -65,6 +66,7 @@
uint64_t _nextPointerFlowId;
BOOL _allowHeadlessExecution;
FlutterBinaryMessengerRelay* _binaryMessenger;
}
- (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*)projectOrNil {
......@@ -92,6 +94,7 @@
_platformViewsController.reset(new flutter::FlutterPlatformViewsController());
[self setupChannels];
_binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self];
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self
......@@ -104,6 +107,8 @@
- (void)dealloc {
[_pluginPublications release];
_binaryMessenger.parent = nil;
[_binaryMessenger release];
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
......@@ -238,42 +243,42 @@
- (void)setupChannels {
_localizationChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/localization"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]]);
_navigationChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/navigation"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]]);
_platformChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/platform"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]]);
_platformViewsChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/platform_views"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterStandardMethodCodec sharedInstance]]);
_textInputChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/textinput"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]]);
_lifecycleChannel.reset([[FlutterBasicMessageChannel alloc]
initWithName:@"flutter/lifecycle"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterStringCodec sharedInstance]]);
_systemChannel.reset([[FlutterBasicMessageChannel alloc]
initWithName:@"flutter/system"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMessageCodec sharedInstance]]);
_settingsChannel.reset([[FlutterBasicMessageChannel alloc]
initWithName:@"flutter/settings"
binaryMessenger:self
binaryMessenger:self.binaryMessenger
codec:[FlutterJSONMessageCodec sharedInstance]]);
_textInputPlugin.reset([[FlutterTextInputPlugin alloc] init]);
......@@ -508,6 +513,10 @@
return _shell->Screenshot(type, base64Encode);
}
- (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
return _binaryMessenger;
}
#pragma mark - FlutterBinaryMessenger
- (void)sendOnChannel:(NSString*)channel message:(NSData*)message {
......@@ -615,7 +624,7 @@
}
- (NSObject<FlutterBinaryMessenger>*)messenger {
return _flutterEngine;
return _flutterEngine.binaryMessenger;
}
- (NSObject<FlutterTextureRegistry>*)textures {
......
......@@ -14,16 +14,20 @@
#include "flutter/fml/platform/darwin/platform_version.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformPlugin.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h"
#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate";
@interface FlutterViewController () <FlutterBinaryMessenger>
@end
@implementation FlutterViewController {
std::unique_ptr<fml::WeakPtrFactory<FlutterViewController>> _weakFactory;
fml::scoped_nsobject<FlutterEngine> _engine;
......@@ -40,6 +44,7 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
BOOL _viewOpaque;
BOOL _engineNeedsLaunch;
NSMutableSet<NSNumber*>* _ongoingTouches;
FlutterBinaryMessengerRelay* _binaryMessenger;
}
#pragma mark - Manage and override all designated initializers
......@@ -50,6 +55,7 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
NSAssert(engine != nil, @"Engine is required");
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self];
_viewOpaque = YES;
_engine.reset([engine retain]);
_engineNeedsLaunch = NO;
......@@ -69,6 +75,7 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
bundle:(NSBundle*)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_binaryMessenger = [[FlutterBinaryMessengerRelay alloc] initWithParent:self];
_viewOpaque = YES;
_weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterViewController>>(self);
_engine.reset([[FlutterEngine alloc] initWithName:@"io.flutter"
......@@ -466,6 +473,8 @@ NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemantics
}
- (void)dealloc {
_binaryMessenger.parent = nil;
[_binaryMessenger release];
[_engine.get() notifyViewControllerDeallocated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
......@@ -978,23 +987,27 @@ constexpr CGFloat kStandardStatusBarHeight = 20.0;
return [_engine.get() platformViewsController];
}
- (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
return _binaryMessenger;
}
#pragma mark - FlutterBinaryMessenger
- (void)sendOnChannel:(NSString*)channel message:(NSData*)message {
[_engine.get() sendOnChannel:channel message:message];
[_engine.get().binaryMessenger sendOnChannel:channel message:message];
}
- (void)sendOnChannel:(NSString*)channel
message:(NSData*)message
binaryReply:(FlutterBinaryReply)callback {
NSAssert(channel, @"The channel must not be null");
[_engine.get() sendOnChannel:channel message:message binaryReply:callback];
[_engine.get().binaryMessenger sendOnChannel:channel message:message binaryReply:callback];
}
- (void)setMessageHandlerOnChannel:(NSString*)channel
binaryMessageHandler:(FlutterBinaryMessageHandler)handler {
NSAssert(channel, @"The channel must not be null");
[_engine.get() setMessageHandlerOnChannel:channel binaryMessageHandler:handler];
[_engine.get().binaryMessenger setMessageHandlerOnChannel:channel binaryMessageHandler:handler];
}
#pragma mark - FlutterTextureRegistry
......
......@@ -572,7 +572,7 @@ AccessibilityBridge::AccessibilityBridge(UIView* view,
previous_routes_({}) {
accessibility_channel_.reset([[FlutterBasicMessageChannel alloc]
initWithName:@"flutter/accessibility"
binaryMessenger:platform_view->GetOwnerViewController().get()
binaryMessenger:platform_view->GetOwnerViewController().get().engine.binaryMessenger
codec:[FlutterStandardMessageCodec sharedInstance]]);
[accessibility_channel_.get() setMessageHandler:^(id message, FlutterReply reply) {
HandleEvent((NSDictionary*)message);
......@@ -582,7 +582,6 @@ AccessibilityBridge::AccessibilityBridge(UIView* view,
AccessibilityBridge::~AccessibilityBridge() {
clearState();
view_.accessibilityElements = nil;
[accessibility_channel_.get() setMessageHandler:nil];
}
UIView<UITextInput>* AccessibilityBridge::textInputView() {
......
......@@ -29,10 +29,8 @@ typedef NS_ENUM(NSInteger, FlutterMouseTrackingMode) {
* Flutter engine in non-interactive mode, or with a drawable Flutter canvas.
*/
FLUTTER_EXPORT
@interface FLEViewController : NSViewController <FlutterBinaryMessenger,
FlutterPluginRegistrar,
FlutterPluginRegistry,
FLEReshapeListener>
@interface FLEViewController
: NSViewController <FlutterPluginRegistrar, FlutterPluginRegistry, FLEReshapeListener>
/**
* The view this controller manages when launched in interactive mode (headless set to false). Must
......@@ -69,4 +67,10 @@ FLUTTER_EXPORT
- (BOOL)launchHeadlessEngineWithAssetsPath:(nonnull NSURL*)assets
commandLineArguments:(nullable NSArray<NSString*>*)arguments;
/**
* The `FlutterBinaryMessenger` associated with this FLEViewController (used for communicating
* with channels).
*/
@property(nonatomic, readonly) NSObject<FlutterBinaryMessenger>* _Nonnull binaryMessenger;
@end
......@@ -72,7 +72,7 @@ static NSString* const kMultilineInputType = @"TextInputType.multiline";
if (self != nil) {
_flutterViewController = viewController;
_channel = [FlutterMethodChannel methodChannelWithName:kTextInputChannel
binaryMessenger:viewController
binaryMessenger:viewController.binaryMessenger
codec:[FlutterJSONMethodCodec sharedInstance]];
__weak FLETextInputPlugin* weakSelf = self;
[_channel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
......
......@@ -70,7 +70,7 @@ struct MouseState {
/**
* Private interface declaration for FLEViewController.
*/
@interface FLEViewController ()
@interface FLEViewController () <FlutterBinaryMessenger>
/**
* A list of additional responders to keyboard events. Keybord events are forwarded to all of them.
......@@ -671,6 +671,11 @@ static void CommonInit(FLEViewController* controller) {
FlutterEngineSendWindowMetricsEvent(_engine, &event);
}
#pragma mark - FlutterBinaryMessengerContainer
- (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
return self;
}
#pragma mark - FlutterBinaryMessenger
- (void)sendOnChannel:(nonnull NSString*)channel message:(nullable NSData*)message {
......
......@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
0D52D3BD22C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
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 */; };
......@@ -71,6 +72,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterBinaryMessengerRelayTest.mm; 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>"; };
......@@ -156,6 +158,7 @@
0D6AB6E622BB409F00EEE540 /* Source */ = {
isa = PBXGroup;
children = (
0D52D3B622C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm */,
0D6AB6E722BB40CF00EEE540 /* FlutterEngineTest.mm */,
);
name = Source;
......@@ -366,6 +369,7 @@
buildActionMask = 2147483647;
files = (
0D6AB6EB22BB40E700EEE540 /* FlutterEngineTest.mm in Sources */,
0D52D3BD22C566D50011DEBD /* FlutterBinaryMessengerRelayTest.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册