mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
FlutterViewController notify will dealloc (flutter/engine#12232)
Made the flutter view controllers dealloc notification more generic and started turning off semantics when the view controller is remotely deleted.
This commit is contained in:
parent
347e9988b1
commit
ab8dae9cc6
@ -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_];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user