Sitelet https://github.com/flutter/packages/pull/12860
Skip to content

[google_maps_flutter] Adopts new async/await Swift Pigeon support - #12860

Merged
auto-submit[bot] merged 4 commits into
flutter:mainfrom
stuartmorgan-g:maps-swift-async-pigeon
Sep 14, 2026
Merged

auto-submit[bot] merged 4 commits into
flutter:mainfrom
stuartmorgan-g:maps-swift-async-pigeon

Conversation

@stuartmorgan-g

Copy link
Copy Markdown
Collaborator

Switches from the callback-based Pigeon API to the new async/await-based API, which is:

  • more idiomatic modern Swift
  • safer, both since it uses Pigeon-generated actor annotations to ensure proper threading, and because it prevents the error case of calling the callback some number of times other than exactly once (which violates the engine API contract)
  • the syntax used by the new FFI backend that we plan to switch to in a follow-up

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 Task boilerplate in many callbacks still because we are implementing APIs that are defined by the Google Maps API, and those are not yet using async and actor annotations, so we have to bridge them in the plugin layer.

Part of flutter/flutter#192720

Pre-Review Checklist

Footnotes

  1. 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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same question for didTapCluster etc,. below.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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.)

@LongCatIsLooong LongCatIsLooong Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm a bit surprised that we don't need the explicit self capture here with Task, what changed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

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.

@stuartmorgan-g stuartmorgan-g added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 14, 2026
@auto-submit
auto-submit Bot merged commit a3ffe32 into flutter:main Sep 14, 2026
13 checks passed
dkwingsmt pushed a commit to dkwingsmt/flutter that referenced this pull request Sep 15, 2026
…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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: google_maps_flutter platform-ios triage-ios Should be looked at in iOS triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants