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

iOS: Migrate FlutterEngine to ARC #55590

Merged
merged 31 commits into from
Oct 4, 2024
Merged

Conversation

cbracken
Copy link
Member

@cbracken cbracken commented Oct 2, 2024

Migrates FlutterEnging from manual reference counting to ARC. Migrates properties from retain to strong and assign to weak (where referencing an Obj-C object).

No semantic changes, therefore no changes to tests.

Issue: flutter/flutter#137801

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide and the C++, Objective-C, Java style guides.
  • I listed at least one issue that this PR fixes in the description above.
  • There weren't as many ARCane memory management gotchas in this patch as I'd have expected.
  • I added new tests to check the change I am making or feature I am adding, or the PR is test-exempt. See testing the engine for instructions on writing and running engine tests.
  • I updated/added relevant documentation (doc comments with ///).
  • I signed the CLA.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@cbracken cbracken marked this pull request as draft October 2, 2024 19:25
@flutter-dashboard
Copy link

This pull request has been changed to a draft. The currently pending flutter-gold status will not be able to resolve until a new commit is pushed or the change is marked ready for review again.

@cbracken cbracken force-pushed the arc-engine branch 3 times, most recently from de3c409 to 301e9f0 Compare October 2, 2024 23:59
@cbracken cbracken marked this pull request as ready for review October 3, 2024 23:38
@cbracken cbracken requested a review from hellohuanlin October 3, 2024 23:40
@cbracken
Copy link
Member Author

cbracken commented Oct 3, 2024

Apologies... this one is a little bigger than the last few.

int64_t _nextTextureId;

BOOL _allowHeadlessExecution;
BOOL _restorationEnabled;
FlutterBinaryMessengerRelay* _binaryMessenger;
FlutterTextureRegistryRelay* _textureRegistry;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two have public getters for NSObject<FlutterBinaryMessenger> and NSObject<FlutterTextureRegistryRelay>.

I'd prefer to hold off on these to a future patch and they're alright as-is for now.

}

- (void)startProfiler {
FML_DCHECK(!_threadHost->name_prefix.empty());
_profiler_metrics = std::make_shared<flutter::ProfilerMetricsIOS>();
__weak FlutterEngine* weakSelf = self;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just preserving existing weak C++ lambda capture of self.

@@ -713,35 +646,30 @@ - (void)setUpChannels {

- (void)maybeSetupPlatformViewChannels {
if (_shell && self.shell.IsSetup()) {
FlutterPlatformPlugin* platformPlugin = _platformPlugin.get();
[_platformChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
[platformPlugin handleMethodCall:call result:result];
Copy link
Member Author

@cbracken cbracken Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and a couple more below -- notice that I've moved all these to use weakSelf.somePlugin.

Technically, this does very slightly change the semantics here, but for the better since if self were to be cleaned up, these will all devolve into no-op messages to nil.

@@ -82,7 +82,7 @@ @interface FlutterPlatformPlugin ()

@implementation FlutterPlatformPlugin

- (instancetype)initWithEngine:(fml::WeakNSObject<FlutterEngine>)engine {
- (instancetype)initWithEngine:(FlutterEngine*)engine {
Copy link
Member Author

@cbracken cbracken Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We assign to _engine, which is a weak property.

@@ -12,7 +12,7 @@
@interface FlutterPlatformPlugin : NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)initWithEngine:(fml::WeakNSObject<FlutterEngine>)engine NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithEngine:(FlutterEngine*)engine NS_DESIGNATED_INITIALIZER;
Copy link
Member Author

@cbracken cbracken Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can make this (and probably some others) (__weak FlutterEngine*) once FlutterViewController.mm (which also #imports this) is migrated to ARC, but either way we're assigning to a weak property.

Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the [labelPrefix copy] is added to init.

This code gives me 30% less heebie jeebies than it did before. Thank you so much for your service 🫡


std::shared_ptr<flutter::PlatformViewsController> _platformViewsController;
flutter::IOSRenderingAPI _renderingApi;
std::shared_ptr<flutter::ProfilerMetricsIOS> _profiler_metrics;
std::shared_ptr<flutter::SamplingProfiler> _profiler;

// Channels
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 LGTM with one or two fixes and some optional nits. (I did a full audit of all of the blocks in addition to reviewing the diff; I know you did as well, but just as a record that the area most likely to have subtle bugs did get more eyes.)


NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
if (_flutterViewControllerWillDeallocObserver) {
[center removeObserver:_flutterViewControllerWillDeallocObserver];
[_flutterViewControllerWillDeallocObserver release];
}
[center removeObserver:self];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: It's harmless to leave, but this line hasn't been necessary since we dropped iOS 8 support. (The thing above looks like it probably is still because of the way it was registered.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will followup in another PR just to "minimise" the change in this patch, which admittedly there is nothing minimal about at the moment. Mostly just want to work through why it's unnecessary, and it's currently to early in the morning for my brain to do that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally fair :)

To save your brain work later, it's because of this:

If your app targets iOS 9.0 and later or macOS 10.11 and later, and you used addObserver:selector:name:object:, you do not need to unregister the observer. If you forget or are unable to remove the observer, the system cleans up the next time it would have posted to it.

https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver

[self recreatePlatformViewController];
self->_platformViewsController->SetTaskRunner(
[weakSelf](flutter::Shell& shell) {
FlutterEngine* strongSelf = weakSelf;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code isn't safe if the comment you removed was wrong (and even if it happens to currently be safe, we shouldn't leave it this way) because the block is unconditionally using strongSelf. There should be a:

if (!strongSelf) {
  return;
}

right after this line.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch -- did this in a couple others but totally missed it here. This block is expected to return a std::unique_ptr<flutter::PlatformView>, so returning a null one here in the hopes that whoever calls this is careful enough to check it (they are, at the moment):

auto platform_view = on_create_platform_view(*shell.get());
if (!platform_view || !platform_view->GetWeakPtr()) {
return nullptr;
}

@cbracken cbracken added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 4, 2024
@auto-submit auto-submit bot merged commit 449df25 into flutter:main Oct 4, 2024
30 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 4, 2024
@cbracken cbracken deleted the arc-engine branch October 4, 2024 17:00
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Oct 4, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Oct 4, 2024
…156239)

flutter/engine@2054840...d38f5e5

2024-10-04 jonahwilliams@google.com [Impeller] generate mipmaps for toImage. (flutter/engine#55655)
2024-10-04 chris@bracken.jp iOS: Migrate FlutterEngine to ARC (flutter/engine#55590)
2024-10-04 skia-flutter-autoroll@skia.org Roll Skia from 0dfa080b5d71 to e8e0a8c46345 (1 revision) (flutter/engine#55652)
2024-10-04 skia-flutter-autoroll@skia.org Roll Dart SDK from 750b6e44b765 to ecba03620fc8 (1 revision) (flutter/engine#55650)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC matanl@google.com,zra@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
auto-submit bot pushed a commit that referenced this pull request Oct 7, 2024
Causing flakes on the _Mac mac_unopt (Cocoon)_ shard.

This reverts commit 449df25.

Issue: flutter/flutter#156177

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
nick9822 pushed a commit to nick9822/flutter that referenced this pull request Dec 18, 2024
Migrates `FlutterEnging` from manual reference counting to ARC. Migrates properties from `retain` to strong and `assign` to `weak` (where referencing an Obj-C object).

No semantic changes, therefore no changes to tests.

Issue: flutter#137801

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
autosubmit Merge PR when tree becomes green via auto submit App platform-ios
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants