Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit e3742a9

Browse files
authored
iOS Platform View: Fixed overrelease of the observer. (#13093)
1 parent 3fd8777 commit e3742a9

File tree

2 files changed

+43
-10
lines changed

2 files changed

+43
-10
lines changed

shell/platform/darwin/ios/platform_view_ios.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ class PlatformViewIOS final : public PlatformView {
4848
void SetSemanticsEnabled(bool enabled) override;
4949

5050
private:
51+
/// Smart pointer for use with objective-c observers.
52+
/// This guarentees we remove the observer.
53+
class ScopedObserver {
54+
public:
55+
ScopedObserver();
56+
~ScopedObserver();
57+
void reset(id<NSObject> observer);
58+
ScopedObserver(const ScopedObserver&) = delete;
59+
ScopedObserver& operator=(const ScopedObserver&) = delete;
60+
61+
private:
62+
id<NSObject> observer_;
63+
};
64+
5165
fml::WeakPtr<FlutterViewController> owner_controller_;
5266
// Since the `ios_surface_` is created on the platform thread but
5367
// used on the GPU thread we need to protect it with a mutex.
@@ -58,7 +72,7 @@ class PlatformViewIOS final : public PlatformView {
5872
std::unique_ptr<AccessibilityBridge> accessibility_bridge_;
5973
fml::scoped_nsprotocol<FlutterTextInputPlugin*> text_input_plugin_;
6074
fml::closure firstFrameCallback_;
61-
fml::scoped_nsprotocol<NSObject*> dealloc_view_controller_observer_;
75+
ScopedObserver dealloc_view_controller_observer_;
6276

6377
// |PlatformView|
6478
void HandlePlatformMessage(fml::RefPtr<flutter::PlatformMessage> message) override;

shell/platform/darwin/ios/platform_view_ios.mm

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@
5454

5555
// Add an observer that will clear out the owner_controller_ ivar and
5656
// the accessibility_bridge_ in case the view controller is deleted.
57-
dealloc_view_controller_observer_.reset([[NSNotificationCenter defaultCenter]
58-
addObserverForName:FlutterViewControllerWillDealloc
59-
object:owner_controller_.get()
60-
queue:[NSOperationQueue mainQueue]
61-
usingBlock:^(NSNotification* note) {
62-
// Implicit copy of 'this' is fine.
63-
accessibility_bridge_.reset();
64-
owner_controller_.reset();
65-
}]);
57+
dealloc_view_controller_observer_.reset(
58+
[[[NSNotificationCenter defaultCenter] addObserverForName:FlutterViewControllerWillDealloc
59+
object:owner_controller_.get()
60+
queue:[NSOperationQueue mainQueue]
61+
usingBlock:^(NSNotification* note) {
62+
// Implicit copy of 'this' is fine.
63+
accessibility_bridge_.reset();
64+
owner_controller_.reset();
65+
}] retain]);
6666

6767
if (owner_controller_) {
6868
ios_surface_ =
@@ -174,4 +174,23 @@ new AccessibilityBridge(static_cast<FlutterView*>(owner_controller_.get().view),
174174
text_input_plugin_ = plugin;
175175
}
176176

177+
PlatformViewIOS::ScopedObserver::ScopedObserver() : observer_(nil) {}
178+
179+
PlatformViewIOS::ScopedObserver::~ScopedObserver() {
180+
if (observer_) {
181+
[[NSNotificationCenter defaultCenter] removeObserver:observer_];
182+
[observer_ release];
183+
}
184+
}
185+
186+
void PlatformViewIOS::ScopedObserver::reset(id<NSObject> observer) {
187+
if (observer != observer_) {
188+
if (observer_) {
189+
[[NSNotificationCenter defaultCenter] removeObserver:observer_];
190+
[observer_ release];
191+
}
192+
observer_ = observer;
193+
}
194+
}
195+
177196
} // namespace flutter

0 commit comments

Comments
 (0)