Skip to content

[google_maps_flutter] Convert overlay controllers to Swift - #12638

Merged
auto-submit[bot] merged 7 commits into
flutter:mainfrom
stuartmorgan-g:maps-swift-overlays
Aug 27, 2026
Merged

auto-submit[bot] merged 7 commits into
flutter:mainfrom
stuartmorgan-g:maps-swift-overlays

Conversation

@stuartmorgan-g

Copy link
Copy Markdown
Collaborator

This converts GroundOverlayController and TileOverlayController to Swift in the _sdk* packages.

The remaining Obj-C code will be migrated in a series of follow-up PRs to keep the scope of each PR reasonable for review.

The conversion process was:

  • Initial conversion via Gemini, with explicit instruction to keep the structure the same.
  • Side-by-side manual review of the old and new versions of the files.
  • Manual fixes and improvements.

This includes test changes beyond what we would normally expect for a language conversion PR (e.g., name changes from dropping the prefix) because the conversion to Swift exposed a latent issue in the tests. Several tests had a pattern where a helper method was creating a local mapView instance, using it to construct the subcontroller under test, and then returning that subcontroller—at which point the map view goes out of scope. The subcontrollers have weak references to the map view, so it can be deallocated before the test actually runs, and doing so causes the tests to fail (as many operations in the subcontroller no-op when the map view is nil). In cases where the helper is only used once, it can be inlined; in cases where it's used repeatedly we can instead return multiple values and keep the map view alive.

Part of flutter/flutter#119108

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

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Aug 26, 2026

@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 migrates the ground overlay and tile overlay controllers from Objective-C to Swift across the google_maps_flutter_ios_sdk9, google_maps_flutter_ios_sdk10, and shared code packages, updating the main map controllers and unit tests accordingly. Feedback on these changes highlights two main areas for improvement: first, ensuring that the receiver callback in requestTileFor is always invoked to prevent potential resource leaks or rendering hangs in the Google Maps SDK; second, passing nil as the initial icon when creating GMSGroundOverlay in the add method to avoid a redundant and potentially expensive FGMIconFromBitmap call.

Comment on lines +117 to +151
if let position = groundOverlay.position {
guard let zoomLevel = groundOverlay.zoomLevel else {
fatalError("If ground overlay is initialized with position, zoomLevel is required")
}
gmsOverlay = GMSGroundOverlay(
position: CLLocationCoordinate2D(
latitude: position.latitude,
longitude: position.longitude
),
icon: FGMIconFromBitmap(groundOverlay.image, assetProvider, screenScale),
zoomLevel: CGFloat(zoomLevel.doubleValue)
)
} else {
isCreatedWithBounds = true
// TODO(stuartmorgan): Convert these to Pigeon error handling rather
// than being fatal. The original Obj-C code used NSAssert instead of
// passing errors back, which isn't how we should handle errors.
guard let bounds = groundOverlay.bounds else {
fatalError("If ground overlay is initialized without position, bounds are required")
}
let gmsBounds = GMSCoordinateBounds(
coordinate: CLLocationCoordinate2D(
latitude: bounds.northeast.latitude,
longitude: bounds.northeast.longitude
),
coordinate: CLLocationCoordinate2D(
latitude: bounds.southwest.latitude,
longitude: bounds.southwest.longitude
)
)
gmsOverlay = GMSGroundOverlay(
bounds: gmsBounds,
icon: FGMIconFromBitmap(groundOverlay.image, assetProvider, screenScale)
)
}

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.

medium

In add, FGMIconFromBitmap is called to create the icon for GMSGroundOverlay. However, immediately after creating the overlay, controller.update is called, which calls GroundOverlayController.update and sets the icon again. We can pass nil as the initial icon to avoid the redundant and potentially expensive FGMIconFromBitmap call.

      if let position = groundOverlay.position {
        guard let zoomLevel = groundOverlay.zoomLevel else {
          fatalError("If ground overlay is initialized with position, zoomLevel is required")
        }
        gmsOverlay = GMSGroundOverlay(
          position: CLLocationCoordinate2D(
            latitude: position.latitude,
            longitude: position.longitude
          ),
          icon: nil,
          zoomLevel: CGFloat(zoomLevel.doubleValue)
        )
      } else {
        isCreatedWithBounds = true
        // TODO(stuartmorgan): Convert these to Pigeon error handling rather
        // than being fatal. The original Obj-C code used NSAssert instead of
        // passing errors back, which isn't how we should handle errors.
        guard let bounds = groundOverlay.bounds else {
          fatalError("If ground overlay is initialized without position, bounds are required")
        }
        let gmsBounds = GMSCoordinateBounds(
          coordinate: CLLocationCoordinate2D(
            latitude: bounds.northeast.latitude,
            longitude: bounds.northeast.longitude
          ),
          coordinate: CLLocationCoordinate2D(
            latitude: bounds.southwest.latitude,
            longitude: bounds.southwest.longitude
          )
        )
        gmsOverlay = GMSGroundOverlay(
          bounds: gmsBounds,
          icon: nil
        )
      }

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.

Indeed; changed as in the other PR.

@stuartmorgan-g

Copy link
Copy Markdown
Collaborator Author

/gemini review

@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 converts the ground overlay and tile overlay controllers from Objective-C to Swift across the google_maps_flutter_ios_sdk10, google_maps_flutter_ios_sdk9, and shared iOS code packages. Feedback on the changes highlights potential stability issues: first, the use of fatalError for validation in GroundOverlayController could crash production applications, where assertionFailure with graceful fallback should be used instead; second, a missing nil check on tileProviderDelegate in TileProviderController could prevent the completion handler from running, potentially causing the Google Maps SDK to hang.

@stuartmorgan-g

Copy link
Copy Markdown
Collaborator Author

/gemini review

@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 converts the ground overlay and tile overlay controllers from Objective-C to Swift across the iOS SDK 9, SDK 10, and shared code packages, alongside corresponding test updates. The review feedback suggests using pixel dimensions and preserving the original scale and orientation in handleResultTile to prevent resolution loss on retina displays, and mapping error.details to a string before nil-coalescing to avoid implicit coercion compiler warnings.

@stuartmorgan-g stuartmorgan-g added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 27, 2026
@auto-submit
auto-submit Bot merged commit 5a23f82 into flutter:main Aug 27, 2026
13 checks passed
pull Bot pushed a commit to Mu-L/flutter that referenced this pull request Aug 28, 2026
…er#191965)

flutter/packages@bd3cbc1...cd4cdd0

2026-08-28 [email protected] [material_ui] Add
all M3 templates and generated code to `temporarily_excluded/` before
migration (flutter/packages#12661)
2026-08-28 [email protected] Roll Flutter from
15d8908 to e8dca90 (58 revisions) (flutter/packages#12660)
2026-08-28 [email protected] [various] Update pigeon dev_dependency to
^27.3.2 (flutter/packages#12615)
2026-08-27 [email protected]
[camera_android_camerax] Enforce CHANGELOG backticks and add eval commit
author check to pre-push-skill (flutter/packages#12624)
2026-08-27 [email protected] [material_ui] Prevent stale async
suggestions in SearchAnchor (flutter/packages#12478)
2026-08-27 [email protected] [go_router_builder] Support analyzer 14
(flutter/packages#12614)
2026-08-27 [email protected] [cupertino_ui] Use super parameters in
more places (flutter/packages#12459)
2026-08-27 [email protected]
[material_ui] Remove no-shuffle from progress indicator test
(flutter/packages#12505)
2026-08-27 [email protected]
[two_dimensional_scrollables] Activate leak testing and fix memory leaks
(flutter/packages#11653)
2026-08-27 [email protected] [material_ui] Add
helper methods in gen_defaults template (flutter/packages#12637)
2026-08-27 [email protected] [cupertino_ui] fix CupertinoIcons
font not being included in examples and fix TextEditingController leaks
(flutter/packages#12228)
2026-08-27 [email protected]
[camera_android_camerax] Check Git hooks configuration in
check-readiness skill (flutter/packages#12628)
2026-08-27 [email protected] [ci] sync back pr
for branch release only run when release succeeds
(flutter/packages#12581)
2026-08-27 [email protected] [google_maps_flutter] Convert overlay
controllers to Swift (flutter/packages#12638)
2026-08-27 [email protected]
[go_router_builder] Fixes text golden test to ignore platform specific
newline (flutter/packages#12652)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] 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
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…2638)

This converts GroundOverlayController and TileOverlayController to Swift in the `_sdk*` packages.

The remaining Obj-C code will be migrated in a series of follow-up PRs to keep the scope of each PR reasonable for review.

The conversion process was:
- Initial conversion via Gemini, with explicit instruction to keep the structure the same.
- Side-by-side manual review of the old and new versions of the files.
- Manual fixes and improvements.

This includes test changes beyond what we would normally expect for a language conversion PR (e.g., name changes from dropping the prefix) because the conversion to Swift exposed a latent issue in the tests. Several tests had a pattern where a helper method was creating a local `mapView` instance, using it to construct the subcontroller under test, and then returning that subcontroller—at which point the map view goes out of scope. The subcontrollers have weak references to the map view, so it can be deallocated before the test actually runs, and doing so causes the tests to fail (as many operations in the subcontroller no-op when the map view is nil). In cases where the helper is only used once, it can be inlined; in cases where it's used repeatedly we can instead return multiple values and keep the map view alive.

Part of flutter/flutter#119108

## Pre-Review Checklist

[^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.
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…2638)

This converts GroundOverlayController and TileOverlayController to Swift in the `_sdk*` packages.

The remaining Obj-C code will be migrated in a series of follow-up PRs to keep the scope of each PR reasonable for review.

The conversion process was:
- Initial conversion via Gemini, with explicit instruction to keep the structure the same.
- Side-by-side manual review of the old and new versions of the files.
- Manual fixes and improvements.

This includes test changes beyond what we would normally expect for a language conversion PR (e.g., name changes from dropping the prefix) because the conversion to Swift exposed a latent issue in the tests. Several tests had a pattern where a helper method was creating a local `mapView` instance, using it to construct the subcontroller under test, and then returning that subcontroller—at which point the map view goes out of scope. The subcontrollers have weak references to the map view, so it can be deallocated before the test actually runs, and doing so causes the tests to fail (as many operations in the subcontroller no-op when the map view is nil). In cases where the helper is only used once, it can be inlined; in cases where it's used repeatedly we can instead return multiple values and keep the map view alive.

Part of flutter/flutter#119108

## Pre-Review Checklist

[^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.
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants