未验证 提交 5075172f 编写于 作者: G gaaclarke 提交者: GitHub

FlutterViewController notify will dealloc (#12232)

Made the flutter view controllers dealloc notification more
generic and started turning off semantics when the view controller
is remotely deleted.
上级 1a2c16b3
......@@ -33,6 +33,7 @@
@property(nonatomic, readonly) NSMutableDictionary* pluginPublications;
@property(nonatomic, readwrite, copy) NSString* isolateId;
@property(nonatomic, retain) id<NSObject> flutterViewControllerWillDeallocObserver;
@end
@interface FlutterEngineRegistrar : NSObject <FlutterPluginRegistrar>
......@@ -111,6 +112,7 @@
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
[_flutterViewControllerWillDeallocObserver release];
[super dealloc];
}
......@@ -167,12 +169,21 @@
_viewController = [viewController getWeakPtr];
self.iosPlatformView->SetOwnerViewController(_viewController);
[self maybeSetupPlatformViewChannels];
self.flutterViewControllerWillDeallocObserver =
[[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
object:viewController
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification* note) {
[self notifyViewControllerDeallocated];
}];
}
- (void)notifyViewControllerDeallocated {
if (!_allowHeadlessExecution) {
[self destroyContext];
}
_viewController.reset();
}
- (void)destroyContext {
......
......@@ -44,7 +44,6 @@
- (FlutterTextInputPlugin*)textInputPlugin;
- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil;
- (BOOL)createShell:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil;
- (void)notifyViewControllerDeallocated;
@end
......
......@@ -25,6 +25,8 @@
NSNotificationName const FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate";
NSNotificationName const FlutterViewControllerWillDealloc = @"FlutterViewControllerWillDealloc";
// This is left a FlutterBinaryMessenger privately for now to give people a chance to notice the
// change. Unfortunately unless you have Werror turned on, incompatible pointers as arguments are
// just a warning.
......@@ -521,7 +523,9 @@ typedef enum UIAccessibilityContrast : NSInteger {
}
- (void)dealloc {
[_engine.get() notifyViewControllerDeallocated];
[[NSNotificationCenter defaultCenter] postNotificationName:FlutterViewControllerWillDealloc
object:self
userInfo:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_ongoingTouches release];
[super dealloc];
......
......@@ -12,6 +12,23 @@
#error ARC must be enabled!
#endif
extern NSNotificationName const FlutterViewControllerWillDealloc;
/// A simple mock class for FlutterEngine.
///
/// OCMockClass can't be used for FlutterEngine sometimes because OCMock retains arguments to
/// invocations and since the init for FlutterViewController calls a method on the
/// FlutterEngine it creates a retain cycle that stops us from testing behaviors related to
/// deleting FlutterViewControllers.
@interface MockEngine : NSObject
@end
@implementation MockEngine
- (void)setViewController:(FlutterViewController*)viewController {
// noop
}
@end
@interface FlutterViewControllerTest : XCTestCase
@end
......@@ -244,4 +261,22 @@ typedef enum UIAccessibilityContrast : NSInteger {
return mockTraitCollection;
}
- (void)testWillDeallocNotification {
XCTestExpectation* expectation =
[[XCTestExpectation alloc] initWithDescription:@"notification called"];
id engine = [[MockEngine alloc] init];
FlutterViewController* realVC = [[FlutterViewController alloc] initWithEngine:engine
nibName:nil
bundle:nil];
id observer =
[[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification* _Nonnull note) {
[expectation fulfill];
}];
realVC = nil;
[self waitForExpectations:@[ expectation ] timeout:1.0];
}
@end
......@@ -12,6 +12,9 @@
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
FLUTTER_EXPORT
extern NSNotificationName const FlutterViewControllerWillDealloc;
@interface FlutterViewController ()
- (fml::WeakPtr<FlutterViewController>)getWeakPtr;
......
......@@ -52,6 +52,7 @@ class PlatformViewIOS final : public PlatformView {
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
fml::scoped_nsprotocol<FlutterTextInputPlugin*> text_input_plugin_;
fml::closure firstFrameCallback_;
fml::scoped_nsprotocol<NSObject*> dealloc_view_controller_observer_;
// |PlatformView|
void HandlePlatformMessage(fml::RefPtr<flutter::PlatformMessage> message) override;
......
......@@ -49,6 +49,19 @@ void PlatformViewIOS::SetOwnerViewController(fml::WeakPtr<FlutterViewController>
accessibility_bridge_.reset();
}
owner_controller_ = owner_controller;
// Add an observer that will clear out the owner_controller_ ivar and
// the accessibility_bridge_ in case the view controller is deleted.
dealloc_view_controller_observer_.reset([[NSNotificationCenter defaultCenter]
addObserverForName:FlutterViewControllerWillDealloc
object:owner_controller_.get()
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification* note) {
// Implicit copy of 'this' is fine.
accessibility_bridge_.reset();
owner_controller_.reset();
}]);
if (owner_controller_) {
ios_surface_ =
[static_cast<FlutterView*>(owner_controller.get().view) createSurface:gl_context_];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册