Repository navigation
[google_maps_flutter] Adopts new async/await Swift Pigeon support - #12860
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the google_maps_flutter iOS packages (sdk9, sdk10, and shared) to adopt the new Pigeon async Swift support, converting callback-based asynchronous methods to Swift's async/throws syntax. Feedback on the changes identifies potential memory retention issues in TileOverlayController.swift across all three packages due to capturing self strongly inside the asynchronous Task closures, and recommends capturing self weakly to prevent delayed deallocation.
| @@ -86,7 +86,9 @@ class CirclesController { | |||
|
|
|||
| func didTapCircle(withIdentifier identifier: String) { | |||
There was a problem hiding this comment.
I assume this method can only be called on the main thread. Shouldn't this method be marked as @MainActor instead, or use MainActor.assumeIsolated in the implementation if that's not an option?
There was a problem hiding this comment.
Same question for didTapCluster etc,. below.
There was a problem hiding this comment.
Technically we don't know what thread this is called on, because calls that end up here start their life as a callback from the Google Maps SDK, and it doesn't seem to document it. Those calls do pass in a GMSMapView, and that's supposed to be main-thread-access-only, so I would certainly hope that they are coming in on the main thread, but we've never actually had any of the code assert that.
I think adding annotations everywhere is probably out of scope for this PR. It would probably be a good idea for someone to do a pass over the entire plugin (and really, all of our plugins) later and liberally sprinkle them with MainActor annotations so that all of the requirements that are currently implicit (e.g., all calls from the engine are coming on the main thread) are explicit. That will be complicated in the short term by the fact that the engine doesn't annotate its APIs yet, so plugins will need a bunch of assumeIsolateds everywhere the engine calls into them. For Maps, someone will need to decide whether we should assumeIsolated on the calls from the SDK given that it would be pretty weird for them to pass a main-thread object into a callback on a non-main thread, or explicitly dispatch to the main actor every time the SDK calls into the plugin.
(This did make me realize that I don't need all the @MainActor annotations on the tasks in these implementation methods though, because the code being awaited in the task already have the annotations, so I removed those.)
There was a problem hiding this comment.
Also just want to double check that MapEventDelegate is not meant to be implemented by app code so it's fine for the delegate methods to be invoked asynchronously as long as the events are still fifo?
There was a problem hiding this comment.
MapEventDelegate sends platform messages (under the current implementation) via Pigeon to the Dart side of the app's codebase, so that events can be handled there. But those have always been async once they hit the engine since that's how the platform channel system works.
| DispatchQueue.main.async { [weak self] in | ||
| guard let self = self, let tileProviderDelegate = self.tileProviderDelegate else { | ||
| Task { @MainActor in | ||
| guard let tileProviderDelegate = self.tileProviderDelegate else { |
There was a problem hiding this comment.
I'm a bit surprised that we don't need the explicit self capture here with Task, what changed?
There was a problem hiding this comment.
See this reply to the Gemini review; I realized that the weak self was adding complication without any actual benefit. And we don't need an explicit capture for a non-weak self because Task is considered low-risk for leaks (since they aren't owned persistently like a general lambda), so there's no warning about not being explicit.
…r#192809) flutter/packages@9caa77c...bebbb57 2026-09-15 5684363+tenninebt@users.noreply.github.com [google_maps_flutter_platform_interface] Add onPointOfInterestTap support (flutter/packages#12752) 2026-09-14 stuartmorgan@google.com [google_maps_flutter] Adopts new async/await Swift Pigeon support (flutter/packages#12860) 2026-09-14 109692895+Massinissa-Mouhoub@users.noreply.github.com [material_ui] Fix `todayBorder` color being overridden by `todayForegroundColor` in `YearPicker` (flutter/packages#12697) 2026-09-13 engine-flutter-autoroll@skia.org Roll Flutter from 2553f89 to 8b3e8f5 (4 revisions) (flutter/packages#12856) 2026-09-12 stuartmorgan@google.com [google_maps_flutter] Convert remaining code to Swift (flutter/packages#12768) 2026-09-12 engine-flutter-autoroll@skia.org Roll Flutter from 63b9518 to 2553f89 (62 revisions) (flutter/packages#12855) 2026-09-12 engine-flutter-autoroll@skia.org Roll Flutter (stable) from d3b14c8 to 9584c67 (15 revisions) (flutter/packages#12854) 2026-09-12 36861262+QuncCccccc@users.noreply.github.com [material_ui] Update gen_defaults color helper (flutter/packages#12846) 2026-09-11 brunocorona.alcantar@gmail.com [material_ui] Port flutter/flutter flutter#185475 "Accessibility: Add semanticLabel to MenuAnchor" (flutter/packages#12806) If this roll has caused a breakage, revert this CL and set the roller to dry run mode using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@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
Switches from the callback-based Pigeon API to the new async/await-based API, which is:
I verified that with this version of Pigeon we are no longer seeing thread violation logging in manual testing (see flutter/flutter#192199)
There is some extra
Taskboilerplate in many callbacks still because we are implementing APIs that are defined by the Google Maps API, and those are not yet usingasyncand actor annotations, so we have to bridge them in the plugin layer.Part of flutter/flutter#192720
Pre-Review Checklist
[shared_preferences]///).Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2