diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md index b4326e884c99..710eae1a5cfc 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md @@ -1,3 +1,9 @@ +## 2.18.5 + +* Updates README to indicate that this package will not receive feature updates + going forward. Please see the README for information about adopting one of + the maintained implementation packages. + ## 2.18.4 * Fixes a potential compilation issue in tile downscaling. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/CONTRIBUTING.md b/packages/google_maps_flutter/google_maps_flutter_ios/CONTRIBUTING.md index 5779bf8d56c0..79b11df33038 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/CONTRIBUTING.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/CONTRIBUTING.md @@ -1,9 +1,6 @@ # Code sharing -This package shares most of its code with the other `google_maps_flutter_ios_*` -packages in this repository, so after changing any code files in this package -run: -`dart run tool/sync_shared_files.dart` - -See [the shared directory README](../google_maps_flutter_ios_shared_code/README.md) -for more details. +This package is essentially frozen; future development is only expected to +happen in the `_sdk*` variants, as this package cannot share code due to +being unable to adopt Swift. Only critical fixes should be made in this +package. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/README.md b/packages/google_maps_flutter/google_maps_flutter_ios/README.md index 9a4b841107f4..d3f8ddf4b65a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/README.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios/README.md @@ -5,6 +5,9 @@ The default iOS implementation of [`google_maps_flutter`][1]. This package will use Google Maps SDK 8.4, 9.x, or 10.x, depending on your application's minimum deployment target. +**Note**: This package will not receive new feature updates. All clients are +encouraged to adopt one of the [SDK-specific implementations](#alternate-implementations). + ## Usage This package is [endorsed][2], which means you can simply use diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml index c5fe13b0ac51..601b3f8abe18 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_ios description: iOS implementation of the google_maps_flutter plugin. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.18.4 +version: 2.18.5 environment: sdk: ^3.10.0 diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/tool/run_tests.dart b/packages/google_maps_flutter/google_maps_flutter_ios/tool/run_tests.dart deleted file mode 100644 index af88ecc57b9c..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios/tool/run_tests.dart +++ /dev/null @@ -1,184 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: avoid_print - -// Ensures that all files that are intended to be shared between -// google_maps_flutter_ios_* packages are in sync with the shared source of -// truth. See google_maps_flutter_ios_shared_code/README.md for details. -// -// Called from the custom-tests CI action. - -import 'dart:async'; -import 'dart:io'; - -import 'package:path/path.dart' as p; - -import 'utils.dart'; - -Future main(List args) async { - // There's no reason to run this on multiple platforms in CI, so limit it to - // macOS where local development of this package will be happening. - if (!Platform.isMacOS) { - print('Skipping for non-macOS host'); - exit(0); - } - - final Directory packageRoot = Directory(p.dirname(Platform.script.path)).parent; - final String packageName = p.basename(packageRoot.path); - final sharedSourceRoot = Directory( - p.join(packageRoot.parent.path, 'google_maps_flutter_ios_shared_code'), - ); - - bool passesValidation = await _validatePackageSharedCode( - packageRoot, - packageName, - sharedSourceRoot: sharedSourceRoot, - log: true, - ); - - print( - '\nChecking for unshared source files that are not in ' - 'tool/unshared_source_files.dart...', - ); - final List unsharedFiles = unexpectedUnsharedSourceFiles( - packageRoot, - packageName, - sharedSourceRoot, - ); - if (unsharedFiles.isEmpty) { - print(' No unexpected unshared files.'); - } else { - passesValidation = false; - for (final file in unsharedFiles) { - print(' $file is not shared'); - } - } - - if (!passesValidation) { - print(''' - -If the changes you made should be shared with other copies of the -implementation, copy the changes to google_maps_flutter_ios_* directories: - dart run tool/sync_shared_files.dart -To validate that the changes have been shared correctly, run this tool again. - -If the changes you made should only be made to one copy of the implementation, -discuss with your reviewer or #hackers-ecosystem on Discord about the best -approach to sharing as much code as can still be shared. - -For more information on the code sharing structure used by this package, see -the google_maps_flutter_ios_shared_code/README.md file. -'''); - exit(1); - } - - // If everything else passed, sanity-check the other implementation packages. - // Full diff evaluation is done by the copy of this script in each - // implementation package, but if someone edits the shared code without - // updating the other packages, this will catch it. This is useful both - // locally, where people are unlikely to run the tests in every package, and - // in CI, where if there are no changes to an implementation package the CI - // for that package will be skipped. - print('\nChecking other implementation packages...'); - final failingPackages = []; - for (final FileSystemEntity entity in packageRoot.parent.listSync()) { - final String packageName = p.basename(entity.path); - if (entity is! Directory || - !packageName.startsWith('google_maps_flutter_ios_') || - packageName == 'google_maps_flutter_ios_shared_code') { - continue; - } - if (!await _validatePackageSharedCode( - entity, - packageName, - sharedSourceRoot: sharedSourceRoot, - log: false, - )) { - failingPackages.add(packageName); - } - } - - if (failingPackages.isEmpty) { - print(' No unexpected diffs found.'); - } else { - print(''' - The following packages do not match the shared source code: -${failingPackages.map((p) => ' $p').join('\n')} - -If you manually synchronized changes to the shared code, you will also need to -copy those changes to the other implementation packages. In the future, consider -using sync_shared_files.dart instead of copying changes to the shared source -manually. -'''); - exit(1); - } -} - -/// Validates that the shared code in [packageRoot] matches the shared source of -/// truth. -/// -/// Returns true if the package matches the shared source of truth. -Future _validatePackageSharedCode( - Directory packageRoot, - String packageName, { - required Directory sharedSourceRoot, - required bool log, -}) async { - var hasDiffs = false; - for (final FileSystemEntity entity in sharedSourceRoot.listSync(recursive: true)) { - if (entity is! File) { - continue; - } - final String relativePath = p.relative(entity.path, from: sharedSourceRoot.path); - // The shared source README.md is not part of the shared source of truth, - // just an explanation of this source-sharing system. - if (relativePath == 'README.md') { - continue; - } - // Ignore .DS_Store files, which may be created in the shared source - // directory by the OS. - if (relativePath.endsWith('.DS_Store')) { - continue; - } - - // Adjust the paths to account for the package name being part of the - // directory structure for Swift packages. - final String packagePath = p.join( - packageRoot.path, - packageRelativePathForSharedSourceRelativePath(packageName, relativePath), - ); - - if (log) { - print('Validating $relativePath'); - } - final packageFile = File(packagePath); - if (!packageFile.existsSync()) { - if (log) { - print(' File $relativePath does not exist in $packageName'); - } - hasDiffs = true; - continue; - } - final String expectedContents = normalizedFileContents(entity); - final String contents = normalizedFileContents(packageFile); - if (contents != expectedContents) { - if (log) { - print(' File $relativePath does not match expected contents:'); - await _printDiff(entity, packageFile); - } - hasDiffs = true; - } - } - return !hasDiffs; -} - -Future _printDiff(File expected, File actual) async { - final Process process = await Process.start('diff', [ - '-u', - expected.absolute.path, - actual.absolute.path, - ], mode: ProcessStartMode.inheritStdio); - await process.exitCode; -} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/tool/sync_shared_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios/tool/sync_shared_files.dart deleted file mode 100644 index 8711068a5604..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios/tool/sync_shared_files.dart +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: avoid_print - -// Synchronizes files that are intended to be shared between -// google_maps_flutter_ios_* packages with the shared source of truth and other -// copies. See google_maps_flutter_ios_shared_code/README.md for details. - -import 'dart:async'; -import 'dart:io'; - -import 'package:path/path.dart' as p; - -import 'utils.dart'; - -const String _sharedSourceRootName = 'google_maps_flutter_ios_shared_code'; - -Future main(List args) async { - final Directory packageRoot = Directory(p.dirname(Platform.script.path)).parent; - final String packageName = p.basename(packageRoot.path); - final sharedSourceRoot = Directory(p.join(packageRoot.parent.path, _sharedSourceRootName)); - - _syncSharedFiles(packageRoot, packageName, sharedSourceRoot); - _reportUnsharedFiles(packageRoot, packageName, sharedSourceRoot); -} - -void _syncSharedFiles(Directory packageRoot, String packageName, Directory sharedSourceRoot) { - final List otherImplementationPackages = sharedSourceRoot.parent - .listSync() - .whereType() - .map((e) => p.basename(e.path)) - .where( - (name) => - name.startsWith('google_maps_flutter_ios') && - name != _sharedSourceRootName && - name != packageName, - ) - .toList(); - - final copiedFiles = []; - final missingFiles = []; - for (final FileSystemEntity entity in sharedSourceRoot.listSync(recursive: true)) { - if (entity is! File) { - continue; - } - final String relativePath = p.relative(entity.path, from: sharedSourceRoot.path); - // The shared source README.md is not part of the shared source of truth, - // just an explanation of this source-sharing system. - if (relativePath == 'README.md') { - continue; - } - - // Adjust the paths to account for the package name being part of the - // directory structure for Swift packages. - final String packagePath = p.join( - packageRoot.path, - packageRelativePathForSharedSourceRelativePath(packageName, relativePath), - ); - - final packageFile = File(packagePath); - if (!packageFile.existsSync()) { - missingFiles.add(relativePath); - continue; - } - final String sharedContents = normalizedFileContents(entity); - final String newContents = normalizedFileContents(packageFile); - if (newContents != sharedContents) { - copiedFiles.add(relativePath); - // Copy to shared source. - _syncFile(packageFile, entity.path, 'google_maps_flutter_ios'); - // Copy to other implementation packages. - for (final otherPackageName in otherImplementationPackages) { - final String otherPackagePath = p.join( - packageRoot.parent.path, - otherPackageName, - packageRelativePathForSharedSourceRelativePath(otherPackageName, relativePath), - ); - _syncFile(packageFile, otherPackagePath, otherPackageName); - } - } - } - - if (copiedFiles.isNotEmpty) { - print('Copied files:'); - for (final file in copiedFiles) { - print(' $file'); - } - } - if (missingFiles.isNotEmpty) { - print('This package is missing the following files from the shared source:'); - for (final file in missingFiles) { - print(' $file'); - } - print( - 'If these files should no longer be shared, remove them from the shared source.\n' - 'If they should no longer exist at all, remove them from all copies of the package.', - ); - } -} - -/// Syncs a file from the given source to a destination package. -/// -/// If the file needs special handling of package names that appear within the -/// contents of the file, it will update the package name in the file to match -/// the destination package name. -void _syncFile(File source, String destinationPath, String destinationPackageName) { - source.copySync(destinationPath); - if ([ - // The Pigeon definition file has output paths that must use the - // package name, to follow Swift package naming rules. - '/pigeons/', - // The mock needs to import the package. - '.mocks.dart', - ].any((pattern) => source.absolute.path.contains(pattern))) { - updatePackageNameInPathReferences(File(destinationPath), destinationPackageName); - } - // Native unit tests need to import the Swift package. - if (source.absolute.path.contains('/RunnerTests/')) { - updatePackageNameInImports(File(destinationPath), destinationPackageName); - } -} - -void _reportUnsharedFiles(Directory packageRoot, String packageName, Directory sharedSourceRoot) { - final List unsharedFiles = unexpectedUnsharedSourceFiles( - packageRoot, - packageName, - sharedSourceRoot, - ); - - if (unsharedFiles.isNotEmpty) { - print('\nThe following code files are not shared with other packages:'); - for (final file in unsharedFiles) { - print(' $file'); - } - print( - 'If this is intentional, add the .\n' - 'Otherwise, copy the relevant files to $_sharedSourceRootName, then re-run this tool.', - ); - } -} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/tool/unshared_source_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios/tool/unshared_source_files.dart deleted file mode 100644 index 627f7e007ee0..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios/tool/unshared_source_files.dart +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -const intentionallyUnsharedSourceFiles = [ - // Intentionally unshared since it has almost no code, and would need - // special handling for the filename being different. - 'lib/google_maps_flutter_ios.dart', - // Intentionally unshared to isolate import name differences. - 'test/package_specific_test_import.dart', - // Each package will have its own list. - 'tool/unshared_source_files.dart', - // Unshared due to https://github.com/flutter/flutter/issues/183441. - 'ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapsUtilsTrampoline.h', -]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/tool/utils.dart b/packages/google_maps_flutter/google_maps_flutter_ios/tool/utils.dart deleted file mode 100644 index 3fb80a0b7e64..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios/tool/utils.dart +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:path/path.dart' as p; - -import 'unshared_source_files.dart'; - -bool isIntentionallyUnsharedSourceFile(String packageRelativePath) { - return intentionallyUnsharedSourceFiles.contains(packageRelativePath); -} - -List unexpectedUnsharedSourceFiles( - Directory packageRoot, - String packageName, - Directory sharedSourceRoot, -) { - final List codeFiles = packageRoot - .listSync(recursive: true) - .whereType() - // Only report code files. - .where((file) => ['.swift', '.m', '.h', '.dart'].any(file.path.endsWith)) - // Flutter-generated files aren't expected to be shared. - .where((file) => !file.path.contains('GeneratedPluginRegistrant')) - // Ignore intermediate file directories. - .where((file) => !_isInIntermediateDirectory(file.path)) - .toList(); - - final unsharedFiles = []; - for (final file in codeFiles) { - final String relativePath = p.relative(file.path, from: packageRoot.path); - if (isIntentionallyUnsharedSourceFile(relativePath)) { - continue; - } - final String sharedPath = p.join( - sharedSourceRoot.path, - sharedSourceRelativePathForPackagePath(relativePath), - ); - final sharedFile = File(sharedPath); - if (!sharedFile.existsSync()) { - unsharedFiles.add(relativePath); - } - } - return unsharedFiles; -} - -/// Adjusts a package-relative path to account for the package name being part of -/// the directory structure for Swift packages. -String sharedSourceRelativePathForPackagePath(String packageRelativePath) { - return packageRelativePath.replaceAll( - RegExp(r'/google_maps_flutter_ios[_\w\d]*/'), - '/google_maps_flutter_ios/', - ); -} - -/// Adjusts a shared-source-relative path to account for the package name being -/// part of the directory structure for Swift packages. -String packageRelativePathForSharedSourceRelativePath( - String packageName, - String sharedSourceRelativePath, -) { - return sharedSourceRelativePath.replaceAll('/google_maps_flutter_ios/', '/$packageName/'); -} - -/// Returns the contents of the file with any differences caused only by the -/// package name removed. -String normalizedFileContents(File file) { - return file - .readAsStringSync() - // Ignore differences caused only by the package name. - .replaceAll(RegExp(r'google_maps_flutter_ios_[\w\d]+'), 'google_maps_flutter_ios') - // Package name diffs could change line wrapping, so collapse whitespace. - .replaceAll(RegExp(r'[\s\n]+'), ' ') - .trim(); -} - -/// Updates the contents of [file] to replace any occurrences of variants of the -/// package name in things that look like paths with [packageName]. -/// -/// This should only be used on files where this is the only option, and where -/// the diffs are known to be safe, as not all instances of the package name -/// should be replaced in all files. -void updatePackageNameInPathReferences(File file, String packageName) { - final String newContents = file.readAsStringSync().replaceAllMapped( - RegExp(r'google_maps_flutter_ios[_\w\d]*([:/])'), - (match) => '$packageName${match.group(1)}', - ); - file.writeAsStringSync(newContents); -} - -/// Updates the contents of [file] to replace any occurrences of variants of the -/// package name in Obj-C or Swift import statements. -/// -/// This is necessary for native unit tests, which need to import the Swift -/// package by name. -void updatePackageNameInImports(File file, String packageName) { - final String newContents = file - .readAsStringSync() - // Package imports. - .replaceAllMapped( - RegExp(r'^(@?(?:testable )?)import google_maps_flutter_ios[_\w\d]*(;?)$', multiLine: true), - (match) => '${match.group(1)}import $packageName${match.group(2)}', - ) - // Bridging header. - .replaceAllMapped( - RegExp(r'^#import '#import <$packageName/', - ); - file.writeAsStringSync(newContents); -} - -bool _isInIntermediateDirectory(String path) { - return [ - '.dart_tool', - '.symlinks', - '.build', - 'build', - 'ephemeral', - 'Pods', - ].any((dir) => path.contains('/$dir/')); -} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/CHANGELOG.md index 59856f19dbec..6257abe68c0e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.18.6 + +* Converts parts of the implementation to Swift. + ## 2.18.5 * Fixes a potential compilation issue in tile downscaling. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/GoogleMapsTests.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/GoogleMapsTests.swift index ea77ef73992b..c8105f0623a5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/GoogleMapsTests.swift +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/GoogleMapsTests.swift @@ -60,7 +60,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { @Test func plugin() { // Verify that creating an actual plugin instance succeeds. - let _ = FGMGoogleMapsPlugin() + let _ = GoogleMapsPlugin() } @Test func frameObserver() { @@ -69,7 +69,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { options.frame = frame options.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0) let mapView = PartiallyMockedMapView(options: options) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -86,20 +86,6 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { #expect(mapView.frameObserverCount == 0) } - @Test func mapsServiceSync() { - // The API requires a registrar, but this test doesn't actually use it, so just pass in a - // dummy object rather than set up a full mock. - let registrar = StubPluginRegistrar() - let factory1 = FGMGoogleMapFactory(registrar: registrar) - #expect(factory1.sharedMapServices != nil) - let factory2 = FGMGoogleMapFactory(registrar: registrar) - // Test pointer equality, should be same retained singleton +[GMSServices sharedServices] object. - // Retaining the opaque object should be enough to avoid multiple internal initializations, - // but don't test the internals of the GoogleMaps API. Assume that it does what is documented. - // https://developers.google.com/maps/documentation/ios-sdk/reference/interface_g_m_s_services#a436e03c32b1c0be74e072310a7158831 - #expect(factory1.sharedMapServices as AnyObject === factory2.sharedMapServices as AnyObject) - } - @Test func handleResultTileDownsamplesWideGamutImages() throws { let controller = FGMTileProviderController() @@ -128,7 +114,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -160,7 +146,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -200,7 +186,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) let binaryMessenger = StubBinaryMessenger() - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -208,11 +194,8 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { binaryMessenger: binaryMessenger ) - let inspector = FGMMapInspector( - mapController: controller, - messenger: binaryMessenger, - pigeonSuffix: "0" - ) + let inspector = MapInspector(messenger: binaryMessenger, pigeonSuffix: "0") + inspector.controller = controller var error: FlutterError? = nil let cameraPosition = try #require(inspector.cameraPosition(&error)) @@ -263,4 +246,67 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { initialGroundOverlays: [] ) } + + @Test func frameObserverRemovedOnDeinitIfNeverFired() { + let options = GMSMapViewOptions() + options.frame = .zero + options.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0) + let mapView = PartiallyMockedMapView(options: options) + + var controller: GoogleMapController? = GoogleMapController( + mapView: mapView, + viewIdentifier: 0, + creationParameters: emptyCreationParameters(), + assetProvider: TestAssetProvider(), + binaryMessenger: StubBinaryMessenger() + ) + + #expect(mapView.frameObserverCount == 1) + + // Deallocate the controller + controller = nil + + #expect(mapView.frameObserverCount == 0) + } + + @Test func styleErrorPersistsAcrossConfigUpdates() { + let mapView = PartiallyMockedMapView(options: GMSMapViewOptions()) + let controller = GoogleMapController( + mapView: mapView, + viewIdentifier: 0, + creationParameters: emptyCreationParameters(), + assetProvider: TestAssetProvider(), + binaryMessenger: StubBinaryMessenger() + ) + + // Set an invalid style to trigger an error + _ = controller.setMapStyle("invalid json") + #expect(controller.styleError != nil) + + // Update config without style + let config = FGMPlatformMapConfiguration.make( + withCompassEnabled: true, + cameraTargetBounds: nil, + mapType: nil, + minMaxZoomPreference: nil, + rotateGesturesEnabled: nil, + scrollGesturesEnabled: nil, + tiltGesturesEnabled: nil, + trackCameraPosition: nil, + zoomGesturesEnabled: nil, + myLocationEnabled: nil, + myLocationButtonEnabled: nil, + padding: nil, + indoorViewEnabled: nil, + trafficEnabled: nil, + buildingsEnabled: nil, + markerType: .marker, + mapId: nil, + style: nil + ) + controller.interpretMapConfiguration(config) + + // The style error should still be present + #expect(controller.styleError != nil) + } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/RunnerTests-Bridging-Header.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/RunnerTests-Bridging-Header.h index 1ac2adc09fdf..8916ac08031c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/RunnerTests-Bridging-Header.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/example/ios/RunnerTests/RunnerTests-Bridging-Header.h @@ -3,18 +3,13 @@ // found in the LICENSE file. // Import private _Test.h headers from the plugin framework -#import -#import -#import -#import -#import -#import -#import -#import - -@interface FGMGoogleMapFactory (Test) -@property(strong, nonatomic, readonly) id sharedMapServices; -@end +#import +#import +#import +#import +#import +#import +#import @interface FGMTileProviderController (Testing) - (UIImage *)handleResultTile:(nullable UIImage *)tileImage; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10.podspec b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10.podspec index d0f2dd1e2102..f34887e3fe7e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10.podspec +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10.podspec @@ -14,8 +14,8 @@ Downloaded by pub (not CocoaPods). s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios_sdk10' } s.documentation_url = 'https://pub.dev/packages/google_maps_flutter_ios_sdk10' - s.source_files = 'google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/**/*.{h,m}' - s.public_header_files = 'google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/**/*.h' + s.source_files = 'google_maps_flutter_ios_sdk10/Sources/**/*.{h,m,swift}' + s.public_header_files = 'google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/**/*.h' s.dependency 'Flutter' s.dependency 'GoogleMaps', '~> 10.0' # 6.1.3 was the first version to support GoogleMaps 10.x. @@ -26,8 +26,8 @@ Downloaded by pub (not CocoaPods). # Find the Swift runtime when these plugins are built as libraries without `use_frameworks!` s.swift_version = '5.9' s.xcconfig = { - 'LIBRARY_SEARCH_PATHS' => '$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift', - 'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) /usr/lib/swift', + 'LIBRARY_SEARCH_PATHS' => '$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift', + 'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift', # To handle the difference in framework names between CocoaPods and Swift Package Manager. 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) FGM_USING_COCOAPODS=1', } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Package.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Package.swift index 29899ba5c4e5..a4c1427e73c5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Package.swift +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Package.swift @@ -26,6 +26,7 @@ let package = Package( .target( name: "google_maps_flutter_ios_sdk10", dependencies: [ + "google_maps_flutter_ios_sdk10_objc", .product( name: "GoogleMapsUtils", package: "google-maps-ios-utils" @@ -41,6 +42,22 @@ let package = Package( cSettings: [ .headerSearchPath("include/google_maps_flutter_ios_sdk10") ] - ) + ), + .target( + name: "google_maps_flutter_ios_sdk10_objc", + dependencies: [ + .product( + name: "GoogleMapsUtils", + package: "google-maps-ios-utils" + ), + .product( + name: "GoogleMaps", + package: "ios-maps-sdk" + ), + ], + cSettings: [ + .headerSearchPath("include/google_maps_flutter_ios_sdk10_objc") + ] + ), ] ) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGoogleMapController.m deleted file mode 100644 index 5f609c9b00de..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGoogleMapController.m +++ /dev/null @@ -1,997 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import GoogleMapsUtils; - -#import "FGMGoogleMapController.h" -#import "FGMGoogleMapController_Test.h" - -#import "FGMAssetProvider.h" -#import "FGMConversionUtils.h" -#import "FGMGroundOverlayController.h" -#import "FGMHeatmapController.h" -#import "FGMMarkerUserData.h" -#import "FGMTileOverlayController.h" -#import "google_maps_flutter_pigeon_messages.g.h" - -@interface FGMGoogleMapFactory () - -@property(weak, nonatomic) NSObject *registrar; -@property(strong, nonatomic, readonly) id sharedMapServices; - -@end - -@implementation FGMGoogleMapFactory - -@synthesize sharedMapServices = _sharedMapServices; - -- (instancetype)initWithRegistrar:(NSObject *)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSObject *)createArgsCodec { - return FGMGetGoogleMapsFlutterPigeonMessagesCodec(); -} - -- (NSObject *)createWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args { - // Precache shared map services, if needed. - // Retain the shared map services singleton, don't use the result for anything. - (void)[self sharedMapServices]; - - return [[FGMGoogleMapController alloc] initWithFrame:frame - viewIdentifier:viewId - creationParameters:args - registrar:self.registrar]; -} - -- (id)sharedMapServices { - if (_sharedMapServices == nil) { - // Calling this prepares GMSServices on a background thread controlled - // by the GoogleMaps framework. - // Retain the singleton to cache the initialization work across all map views. - _sharedMapServices = [GMSServices sharedServices]; - } - return _sharedMapServices; -} - -@end - -#pragma mark - - -/// Non-test implementation of FGMAssetProvider, wrapping a Flutter plugin -/// registrar. -@interface FGMDefaultAssetProvider : NSObject -@property(weak, nonatomic) NSObject *registrar; - -- (instancetype)initWithRegistrar:(NSObject *)registrar; -@end - -@implementation FGMDefaultAssetProvider - -- (instancetype)initWithRegistrar:(NSObject *)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSString *)lookupKeyForAsset:(NSString *)asset { - return [self.registrar lookupKeyForAsset:asset]; -} - -- (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package { - return [self.registrar lookupKeyForAsset:asset fromPackage:package]; -} - -- (UIImage *)imageNamed:(NSString *)name { - return [UIImage imageNamed:name]; -} - -@end - -#pragma mark - - -/// Non-test implementation of FGMAssetProvider, wrapping a FGMMapsCallbackApi -/// instance. -@interface FGMDefaultMapEventHandler : NSObject -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; - -- (instancetype)initWithCallbackHandler:(FGMMapsCallbackApi *)callbackHandler; -@end - -@implementation FGMDefaultMapEventHandler - -- (instancetype)initWithCallbackHandler:(FGMMapsCallbackApi *)callbackHandler { - self = [super init]; - if (self) { - _callbackHandler = callbackHandler; - } - return self; -} - -- (void)didStartCameraMove { - [self.callbackHandler didStartCameraMoveWithCompletion:^(FlutterError *_){ - }]; -} - -- (void)didMoveCameraToPosition:(FGMPlatformCameraPosition *)cameraPosition { - [self.callbackHandler didMoveCameraToPosition:cameraPosition - completion:^(FlutterError *_){ - }]; -} - -- (void)didIdleCamera { - [self.callbackHandler didIdleCameraWithCompletion:^(FlutterError *_){ - }]; -} - -- (void)didTapAtPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didTapAtPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didLongPressAtPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didLongPressAtPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapMarkerWithIdentifier:(NSString *)markerId { - [self.callbackHandler didTapMarkerWithIdentifier:markerId - completion:^(FlutterError *_){ - }]; -} - -- (void)didStartDragForMarkerWithIdentifier:(NSString *)markerId - atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didStartDragForMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didDragMarkerWithIdentifier:(NSString *)markerId atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didDragMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didEndDragForMarkerWithIdentifier:(NSString *)markerId - atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didEndDragForMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapInfoWindowOfMarkerWithIdentifier:(NSString *)markerId { - [self.callbackHandler didTapInfoWindowOfMarkerWithIdentifier:markerId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapCircleWithIdentifier:(NSString *)circleId { - [self.callbackHandler didTapCircleWithIdentifier:circleId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapCluster:(FGMPlatformCluster *)cluster { - [self.callbackHandler didTapCluster:cluster - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapPolygonWithIdentifier:(NSString *)polygonId { - [self.callbackHandler didTapPolygonWithIdentifier:polygonId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapPolylineWithIdentifier:(NSString *)polylineId { - [self.callbackHandler didTapPolylineWithIdentifier:polylineId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapGroundOverlayWithIdentifier:(NSString *)groundOverlayId { - [self.callbackHandler didTapGroundOverlayWithIdentifier:groundOverlayId - completion:^(FlutterError *_){ - }]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapCallHandler. -@interface FGMMapCallHandler () -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix; - -/// The map controller this inspector corresponds to. -@property(nonatomic, weak) FGMGoogleMapController *controller; -/// The messenger this instance was registered with by Pigeon. -@property(nonatomic, copy) NSObject *messenger; -/// The suffix this instance was registered under with Pigeon. -@property(nonatomic, copy) NSString *pigeonSuffix; -@end - -#pragma mark - - -/// Private declarations of the FGMMapInspector. -@interface FGMMapInspector () - -/// The map controller this inspector corresponds to. -@property(nonatomic, weak) FGMGoogleMapController *controller; -/// The messenger this instance was registered with by Pigeon. -@property(nonatomic, copy) NSObject *messenger; -/// The suffix this instance was registered under with Pigeon. -@property(nonatomic, copy) NSString *pigeonSuffix; -@end - -#pragma mark - - -@interface FGMGoogleMapController () - -@property(nonatomic, strong) GMSMapView *mapView; -@property(nonatomic, strong) FGMMapsCallbackApi *dartCallbackHandler; -@property(nonatomic, strong) FGMDefaultMapEventHandler *mapEventHandler; -@property(nonatomic, assign) BOOL trackCameraPosition; -@property(nonatomic, strong) FGMClusterManagersController *clusterManagersController; -@property(nonatomic, strong) FGMMarkersController *markersController; -@property(nonatomic, strong) FGMPolygonsController *polygonsController; -@property(nonatomic, strong) FGMPolylinesController *polylinesController; -@property(nonatomic, strong) FGMCirclesController *circlesController; - -// The controller that handles heatmaps -@property(nonatomic, strong) FGMHeatmapsController *heatmapsController; -@property(nonatomic, strong) FGMTileOverlaysController *tileOverlaysController; -@property(nonatomic, strong) FGMGroundOverlaysController *groundOverlaysController; -// The resulting error message, if any, from the last attempt to set the map style. -// This is used to provide access to errors after the fact, since the map style is generally set at -// creation time and there's no mechanism to return non-fatal error details during platform view -// initialization. -@property(nonatomic, copy) NSString *styleError; -// The main Pigeon API implementation, separate to avoid lifetime extension. -@property(nonatomic, strong) FGMMapCallHandler *callHandler; -// The inspector API implementation, separate to avoid lifetime extension. -@property(nonatomic, strong) FGMMapInspector *inspector; - -@end - -@implementation FGMGoogleMapController - -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *)registrar { - GMSCameraPosition *camera = - FGMGetCameraPositionForPigeonCameraPosition(creationParameters.initialCameraPosition); - - GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init]; - options.frame = frame; - options.camera = camera; - NSString *mapId = creationParameters.mapConfiguration.mapId; - if (mapId.length > 0) { - options.mapID = [GMSMapID mapIDWithIdentifier:mapId]; - } - - GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options]; - - return [self initWithMapView:mapView - viewIdentifier:viewId - creationParameters:creationParameters - assetProvider:[[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar] - binaryMessenger:registrar.messenger]; -} - -- (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - assetProvider:(NSObject *)assetProvider - binaryMessenger:(NSObject *)binaryMessenger { - if (self = [super init]) { - _mapView = mapView; - - _mapView.accessibilityElementsHidden = NO; - // TODO(cyanglaz): avoid sending message to self in the middle of the init method. - // https://github.com/flutter/flutter/issues/104121 - [self interpretMapConfiguration:creationParameters.mapConfiguration]; - NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; - _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:binaryMessenger - messageChannelSuffix:pigeonSuffix]; - _mapEventHandler = - [[FGMDefaultMapEventHandler alloc] initWithCallbackHandler:_dartCallbackHandler]; - FGMPlatformMarkerType markerType = creationParameters.mapConfiguration.markerType; - _mapView.delegate = self; - _mapView.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; - _clusterManagersController = - [[FGMClusterManagersController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _markersController = [[FGMMarkersController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler - clusterManagersController:_clusterManagersController - assetProvider:assetProvider - markerType:markerType]; - _polygonsController = [[FGMPolygonsController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _polylinesController = [[FGMPolylinesController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _circlesController = [[FGMCirclesController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _heatmapsController = [[FGMHeatmapsController alloc] initWithMapView:_mapView]; - _tileOverlaysController = [[FGMTileOverlaysController alloc] initWithMapView:_mapView - tileProvider:self]; - _groundOverlaysController = - [[FGMGroundOverlaysController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler - assetProvider:assetProvider]; - [_clusterManagersController addClusterManagers:creationParameters.initialClusterManagers]; - [_markersController addMarkers:creationParameters.initialMarkers]; - [_polygonsController addPolygons:creationParameters.initialPolygons]; - [_polylinesController addPolylines:creationParameters.initialPolylines]; - [_circlesController addCircles:creationParameters.initialCircles]; - [_heatmapsController addHeatmaps:creationParameters.initialHeatmaps]; - [_tileOverlaysController addTileOverlays:creationParameters.initialTileOverlays]; - [_groundOverlaysController addGroundOverlays:creationParameters.initialGroundOverlays]; - - // Invoke clustering after markers are added. - [_clusterManagersController invokeClusteringForEachClusterManager]; - - [_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil]; - - _callHandler = [[FGMMapCallHandler alloc] initWithMapController:self - messenger:binaryMessenger - pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsApiWithSuffix(binaryMessenger, _callHandler, pigeonSuffix); - _inspector = [[FGMMapInspector alloc] initWithMapController:self - messenger:binaryMessenger - pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, _inspector, pigeonSuffix); - } - return self; -} - -- (void)dealloc { - // Unregister the API implementations so that they can be released; the registration created an - // owning reference. - SetUpFGMMapsApiWithSuffix(_callHandler.messenger, nil, _callHandler.pigeonSuffix); - SetUpFGMMapsInspectorApiWithSuffix(_inspector.messenger, nil, _inspector.pigeonSuffix); -} - -- (UIView *)view { - return self.mapView; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - if (object == self.mapView && [keyPath isEqualToString:@"frame"]) { - CGRect bounds = self.mapView.bounds; - if (CGRectEqualToRect(bounds, CGRectZero)) { - // The workaround is to fix an issue that the camera location is not current when - // the size of the map is zero at initialization. - // So We only care about the size of the `self.mapView`, ignore the frame changes when the - // size is zero. - return; - } - // We only observe the frame for initial setup. - [self.mapView removeObserver:self forKeyPath:@"frame"]; - [self.mapView moveCamera:[GMSCameraUpdate setCamera:self.mapView.camera]]; - } else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -- (void)showAtOrigin:(CGPoint)origin { - CGRect frame = {origin, self.mapView.frame.size}; - self.mapView.frame = frame; - self.mapView.hidden = NO; -} - -- (void)hide { - self.mapView.hidden = YES; -} - -- (GMSCameraPosition *)cameraPosition { - if (self.trackCameraPosition) { - return self.mapView.camera; - } else { - return nil; - } -} - -- (void)setCamera:(GMSCameraPosition *)camera { - self.mapView.camera = camera; -} - -- (void)setCameraTargetBounds:(GMSCoordinateBounds *)bounds { - self.mapView.cameraTargetBounds = bounds; -} - -- (void)setCompassEnabled:(BOOL)enabled { - self.mapView.settings.compassButton = enabled; -} - -- (void)setIndoorEnabled:(BOOL)enabled { - self.mapView.indoorEnabled = enabled; -} - -- (void)setTrafficEnabled:(BOOL)enabled { - self.mapView.trafficEnabled = enabled; -} - -- (void)setBuildingsEnabled:(BOOL)enabled { - self.mapView.buildingsEnabled = enabled; -} - -- (void)setMapType:(GMSMapViewType)mapType { - self.mapView.mapType = mapType; -} - -- (void)setMinZoom:(float)minZoom maxZoom:(float)maxZoom { - [self.mapView setMinZoom:minZoom maxZoom:maxZoom]; -} - -- (void)setPaddingTop:(float)top left:(float)left bottom:(float)bottom right:(float)right { - self.mapView.padding = UIEdgeInsetsMake(top, left, bottom, right); -} - -- (void)setRotateGesturesEnabled:(BOOL)enabled { - self.mapView.settings.rotateGestures = enabled; -} - -- (void)setScrollGesturesEnabled:(BOOL)enabled { - self.mapView.settings.scrollGestures = enabled; -} - -- (void)setTiltGesturesEnabled:(BOOL)enabled { - self.mapView.settings.tiltGestures = enabled; -} - -- (void)setTrackCameraPosition:(BOOL)enabled { - _trackCameraPosition = enabled; -} - -- (void)setZoomGesturesEnabled:(BOOL)enabled { - self.mapView.settings.zoomGestures = enabled; -} - -- (void)setMyLocationEnabled:(BOOL)enabled { - self.mapView.myLocationEnabled = enabled; -} - -- (void)setMyLocationButtonEnabled:(BOOL)enabled { - self.mapView.settings.myLocationButton = enabled; -} - -/// Sets the map style, returing any error string as well as storing that error in `mapStyle` for -/// later access. -- (NSString *)setMapStyle:(NSString *)mapStyle { - NSString *errorString = nil; - if (mapStyle.length == 0) { - self.mapView.mapStyle = nil; - } else { - NSError *error; - GMSMapStyle *style = [GMSMapStyle styleWithJSONString:mapStyle error:&error]; - if (style) { - self.mapView.mapStyle = style; - } else { - errorString = [error localizedDescription]; - } - } - self.styleError = errorString; - return errorString; -} - -#pragma mark - GMSMapViewDelegate methods - -- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture { - [self.mapEventHandler didStartCameraMove]; -} - -- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position { - if (self.trackCameraPosition) { - [self.mapEventHandler didMoveCameraToPosition:FGMGetPigeonCameraPositionForPosition(position)]; - } -} - -- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position { - [self.mapEventHandler didIdleCamera]; -} - -- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { - if ([marker.userData isKindOfClass:[GMUStaticCluster class]]) { - GMUStaticCluster *cluster = marker.userData; - [self.clusterManagersController didTapCluster:cluster]; - // When NO is returned, the map will focus on the cluster. - return NO; - } - return - [self.markersController didTapMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker)]; -} - -- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker { - [self.markersController - didEndDraggingMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didBeginDraggingMarker:(GMSMarker *)marker { - [self.markersController - didStartDraggingMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker { - [self.markersController didDragMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker { - [self.markersController - didTapInfoWindowOfMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker)]; -} -- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay { - NSString *overlayId = overlay.userData[0]; - if ([self.polylinesController hasPolylineWithIdentifier:overlayId]) { - [self.polylinesController didTapPolylineWithIdentifier:overlayId]; - } else if ([self.polygonsController hasPolygonWithIdentifier:overlayId]) { - [self.polygonsController didTapPolygonWithIdentifier:overlayId]; - } else if ([self.circlesController hasCircleWithIdentifier:overlayId]) { - [self.circlesController didTapCircleWithIdentifier:overlayId]; - } else if ([self.groundOverlaysController hasGroundOverlaysWithIdentifier:overlayId]) { - [self.groundOverlaysController didTapGroundOverlayWithIdentifier:overlayId]; - } -} - -- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.mapEventHandler didTapAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; -} - -- (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.mapEventHandler didLongPressAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; -} - -- (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { - FGMPlatformCameraTargetBounds *cameraTargetBounds = config.cameraTargetBounds; - if (cameraTargetBounds) { - [self setCameraTargetBounds:cameraTargetBounds.bounds - ? FGMGetCoordinateBoundsForPigeonLatLngBounds( - cameraTargetBounds.bounds) - : nil]; - } - NSNumber *compassEnabled = config.compassEnabled; - if (compassEnabled != nil) { - [self setCompassEnabled:compassEnabled.boolValue]; - } - NSNumber *indoorEnabled = config.indoorViewEnabled; - if (indoorEnabled != nil) { - [self setIndoorEnabled:indoorEnabled.boolValue]; - } - NSNumber *trafficEnabled = config.trafficEnabled; - if (trafficEnabled != nil) { - [self setTrafficEnabled:trafficEnabled.boolValue]; - } - NSNumber *buildingsEnabled = config.buildingsEnabled; - if (buildingsEnabled != nil) { - [self setBuildingsEnabled:buildingsEnabled.boolValue]; - } - FGMPlatformMapTypeBox *mapType = config.mapType; - if (mapType) { - [self setMapType:FGMGetMapViewTypeForPigeonMapType(mapType.value)]; - } - FGMPlatformZoomRange *zoomData = config.minMaxZoomPreference; - if (zoomData) { - float minZoom = zoomData.min != nil ? zoomData.min.floatValue : kGMSMinZoomLevel; - float maxZoom = zoomData.max != nil ? zoomData.max.floatValue : kGMSMaxZoomLevel; - [self setMinZoom:minZoom maxZoom:maxZoom]; - } - FGMPlatformEdgeInsets *padding = config.padding; - if (padding) { - [self setPaddingTop:padding.top left:padding.left bottom:padding.bottom right:padding.right]; - } - - NSNumber *rotateGesturesEnabled = config.rotateGesturesEnabled; - if (rotateGesturesEnabled != nil) { - [self setRotateGesturesEnabled:rotateGesturesEnabled.boolValue]; - } - NSNumber *scrollGesturesEnabled = config.scrollGesturesEnabled; - if (scrollGesturesEnabled != nil) { - [self setScrollGesturesEnabled:scrollGesturesEnabled.boolValue]; - } - NSNumber *tiltGesturesEnabled = config.tiltGesturesEnabled; - if (tiltGesturesEnabled != nil) { - [self setTiltGesturesEnabled:tiltGesturesEnabled.boolValue]; - } - NSNumber *trackCameraPosition = config.trackCameraPosition; - if (trackCameraPosition != nil) { - [self setTrackCameraPosition:trackCameraPosition.boolValue]; - } - NSNumber *zoomGesturesEnabled = config.zoomGesturesEnabled; - if (zoomGesturesEnabled != nil) { - [self setZoomGesturesEnabled:zoomGesturesEnabled.boolValue]; - } - NSNumber *myLocationEnabled = config.myLocationEnabled; - if (myLocationEnabled != nil) { - [self setMyLocationEnabled:myLocationEnabled.boolValue]; - } - NSNumber *myLocationButtonEnabled = config.myLocationButtonEnabled; - if (myLocationButtonEnabled != nil) { - [self setMyLocationButtonEnabled:myLocationButtonEnabled.boolValue]; - } - NSString *style = config.style; - if (style) { - [self setMapStyle:style]; - } -} - -#pragma mark - FGMTileProviderDelegate - -- (void)tileWithOverlayIdentifier:(NSString *)tileOverlayId - location:(FGMPlatformPoint *)location - zoom:(NSInteger)zoom - completion:(void (^)(FGMPlatformTile *_Nullable, - FlutterError *_Nullable))completion { - [self.dartCallbackHandler tileWithOverlayIdentifier:tileOverlayId - location:location - zoom:zoom - completion:completion]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapCallHandler. -@implementation FGMMapCallHandler - -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix { - self = [super init]; - if (self) { - _controller = controller; - _messenger = messenger; - _pigeonSuffix = suffix; - _transactionWrapper = [[FGMCATransactionWrapper alloc] init]; - } - return self; -} - -- (void)waitForMapWithError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - // No-op; this call just ensures synchronization with the platform thread. -} - -- (void)updateCirclesByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.circlesController addCircles:toAdd]; - [self.controller.circlesController changeCircles:toChange]; - [self.controller.circlesController removeCirclesWithIdentifiers:idsToRemove]; -} - -- (void)updateHeatmapsByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.heatmapsController addHeatmaps:toAdd]; - [self.controller.heatmapsController changeHeatmaps:toChange]; - [self.controller.heatmapsController removeHeatmapsWithIdentifiers:idsToRemove]; -} - -- (void)updateWithMapConfiguration:(nonnull FGMPlatformMapConfiguration *)configuration - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller interpretMapConfiguration:configuration]; -} - -- (void)updateMarkersByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.markersController addMarkers:toAdd]; - [self.controller.markersController changeMarkers:toChange]; - [self.controller.markersController removeMarkersWithIdentifiers:idsToRemove]; - - // Invoke clustering after markers are added. - [self.controller.clusterManagersController invokeClusteringForEachClusterManager]; -} - -- (void)updateClusterManagersByAdding:(nonnull NSArray *)toAdd - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.clusterManagersController addClusterManagers:toAdd]; - [self.controller.clusterManagersController removeClusterManagersWithIdentifiers:idsToRemove]; -} - -- (void)updatePolygonsByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.polygonsController addPolygons:toAdd]; - [self.controller.polygonsController changePolygons:toChange]; - [self.controller.polygonsController removePolygonWithIdentifiers:idsToRemove]; -} - -- (void)updatePolylinesByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.polylinesController addPolylines:toAdd]; - [self.controller.polylinesController changePolylines:toChange]; - [self.controller.polylinesController removePolylineWithIdentifiers:idsToRemove]; -} - -- (void)updateTileOverlaysByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.tileOverlaysController addTileOverlays:toAdd]; - [self.controller.tileOverlaysController changeTileOverlays:toChange]; - [self.controller.tileOverlaysController removeTileOverlayWithIdentifiers:idsToRemove]; -} - -- (void)updateGroundOverlaysByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.groundOverlaysController addGroundOverlays:toAdd]; - [self.controller.groundOverlaysController changeGroundOverlays:toChange]; - [self.controller.groundOverlaysController removeGroundOverlaysWithIdentifiers:idsToRemove]; -} - -- (nullable FGMPlatformLatLng *) - latLngForScreenCoordinate:(nonnull FGMPlatformPoint *)screenCoordinate - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getLatLng called prior to map initialization" - details:nil]; - return nil; - } - CGPoint point = FGMGetCGPointForPigeonPoint(screenCoordinate); - CLLocationCoordinate2D latlng = [self.controller.mapView.projection coordinateForPoint:point]; - return FGMGetPigeonLatLngForCoordinate(latlng); -} - -- (nullable FGMPlatformPoint *) - screenCoordinatesForLatLng:(nonnull FGMPlatformLatLng *)latLng - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getScreenCoordinate called prior to map initialization" - details:nil]; - return nil; - } - CLLocationCoordinate2D location = FGMGetCoordinateForPigeonLatLng(latLng); - CGPoint point = [self.controller.mapView.projection pointForCoordinate:location]; - return FGMGetPigeonPointForCGPoint(point); -} - -- (nullable FGMPlatformLatLngBounds *)visibleMapRegion: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getVisibleRegion called prior to map initialization" - details:nil]; - return nil; - } - GMSVisibleRegion visibleRegion = self.controller.mapView.projection.visibleRegion; - GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:visibleRegion]; - return FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds); -} - -- (void)moveCameraWithUpdate:(nonnull FGMPlatformCameraUpdate *)cameraUpdate - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate); - if (!update) { - *error = [FlutterError errorWithCode:@"Invalid update" - message:@"Unrecognized camera update" - details:nil]; - return; - } - [self.controller.mapView moveCamera:update]; -} - -- (void)animateCameraWithUpdate:(nonnull FGMPlatformCameraUpdate *)cameraUpdate - duration:(nullable NSNumber *)durationMilliseconds - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate); - if (!update) { - *error = [FlutterError errorWithCode:@"Invalid update" - message:@"Unrecognized camera update" - details:nil]; - return; - } - FGMCATransactionWrapper *transaction = - durationMilliseconds != nil ? self.transactionWrapper : nil; - [transaction begin]; - [transaction setAnimationDuration:[durationMilliseconds doubleValue] / 1000]; - [self.controller.mapView animateWithCameraUpdate:update]; - [transaction commit]; -} - -- (nullable NSNumber *)currentZoomLevel:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.camera.zoom); -} - -- (void)showInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.markersController showMarkerInfoWindowWithIdentifier:markerId error:error]; -} - -- (void)hideInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.markersController hideMarkerInfoWindowWithIdentifier:markerId error:error]; -} - -- (nullable NSNumber *) - isShowingInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - return [self.controller.markersController isInfoWindowShownForMarkerWithIdentifier:markerId - error:error]; -} - -- (nullable NSString *)setStyle:(nonnull NSString *)style - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [self.controller setMapStyle:style]; -} - -- (nullable NSString *)lastStyleError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return self.controller.styleError; -} - -- (void)clearTileCacheForOverlayWithIdentifier:(nonnull NSString *)tileOverlayId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.tileOverlaysController clearTileCacheWithIdentifier:tileOverlayId]; -} - -- (nullable FlutterStandardTypedData *)takeSnapshotWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSMapView *mapView = self.controller.mapView; - if (!mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"takeSnapshot called prior to map initialization" - details:nil]; - return nil; - } - UIGraphicsImageRenderer *renderer = - [[UIGraphicsImageRenderer alloc] initWithSize:mapView.bounds.size]; - // For some unknown reason mapView.layer::renderInContext API returns a blank image on iOS 17. - // So we have to use drawViewHierarchyInRect API. - UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) { - [mapView drawViewHierarchyInRect:mapView.bounds afterScreenUpdates:YES]; - }]; - NSData *imageData = UIImagePNGRepresentation(image); - return imageData ? [FlutterStandardTypedData typedDataWithBytes:imageData] : nil; -} - -- (nullable NSNumber *)isAdvancedMarkersAvailable: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - NSUInteger advancedMarkerFlag = - self.controller.mapView.mapCapabilities & GMSMapCapabilityFlagsAdvancedMarkers; - return [NSNumber numberWithBool:(advancedMarkerFlag != 0)]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapInspector. -@implementation FGMMapInspector - -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix { - self = [super init]; - if (self) { - _controller = controller; - _messenger = messenger; - _pigeonSuffix = suffix; - } - return self; -} - -- (nullable NSNumber *)areBuildingsEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.buildingsEnabled); -} - -- (nullable NSNumber *)areRotateGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.rotateGestures); -} - -- (nullable NSNumber *)areScrollGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.scrollGestures); -} - -- (nullable NSNumber *)areTiltGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.tiltGestures); -} - -- (nullable NSNumber *)areZoomGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.zoomGestures); -} - -- (nullable FGMPlatformTileLayer *) - tileOverlayWithIdentifier:(nonnull NSString *)tileOverlayId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSTileLayer *layer = - [self.controller.tileOverlaysController tileOverlayWithIdentifier:tileOverlayId].layer; - if (!layer) { - return nil; - } - return [FGMPlatformTileLayer makeWithVisible:(layer.map != nil) - fadeIn:layer.fadeIn - opacity:layer.opacity - zIndex:layer.zIndex]; -} - -- (nullable FGMPlatformHeatmap *) - heatmapWithIdentifier:(nonnull NSString *)heatmapId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [self.controller.heatmapsController heatmapWithIdentifier:heatmapId]; -} - -- (nullable NSArray *) - clustersWithIdentifier:(NSString *)clusterManagerId - error:(FlutterError *_Nullable *_Nonnull)error { - return [self.controller.clusterManagersController clustersWithIdentifier:clusterManagerId - error:error]; -} - -- (nullable NSNumber *)isCompassEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.compassButton); -} - -- (nullable NSNumber *)isMyLocationButtonEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.myLocationButton); -} - -- (nullable NSNumber *)isTrafficEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.trafficEnabled); -} - -- (nullable FGMPlatformZoomRange *)zoomRange: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [FGMPlatformZoomRange makeWithMin:@(self.controller.mapView.minZoom) - max:@(self.controller.mapView.maxZoom)]; -} - -- (nullable FGMPlatformGroundOverlay *) - groundOverlayWithIdentifier:(NSString *)groundOverlayId - error:(FlutterError *_Nullable __autoreleasing *)error { - return [self.controller.groundOverlaysController groundOverlayWithIdentifier:groundOverlayId]; -} - -- (nullable FGMPlatformCameraPosition *)cameraPosition: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return FGMGetPigeonCameraPositionForPosition(self.controller.mapView.camera); -} - -@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGoogleMapsPlugin.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGoogleMapsPlugin.m deleted file mode 100644 index 072d675b17b8..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGoogleMapsPlugin.m +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FGMGoogleMapsPlugin.h" - -@import GoogleMaps; - -#pragma mark - GoogleMaps plugin implementation - -// Declares a GMSServices method that was added in SDK 9.2, so that it can be -// conditionally called. It is declared on NSObject to avoid duplicate -// declaration errors when compiling with newer SDKs. -// TODO(stuartmorgan): Remove this once all packages sharing this file require -// SDK 9.2 or later. See https://github.com/flutter/flutter/issues/187106 -@interface NSObject (MapsSDK92Extensions) -+ (void)addInternalUsageAttributionID:(nonnull NSString *)internalUsageAttributionID; -@end - -@implementation FGMGoogleMapsPlugin - -+ (void)registerWithRegistrar:(NSObject *)registrar { - FGMGoogleMapFactory *googleMapFactory = [[FGMGoogleMapFactory alloc] initWithRegistrar:registrar]; - [registrar registerViewFactory:googleMapFactory - withId:@"plugins.flutter.dev/google_maps_ios" - gestureRecognizersBlockingPolicy: - FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded]; - if ([GMSServices respondsToSelector:@selector(addInternalUsageAttributionID:)]) { - [GMSServices addInternalUsageAttributionID:@"gmp_flutter_googlemapsflutter_ios"]; - } -} - -@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapController.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapController.swift new file mode 100644 index 000000000000..b5b822b9442b --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapController.swift @@ -0,0 +1,938 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps +import GoogleMapsUtils + +#if canImport(google_maps_flutter_ios_sdk9_objc) + import google_maps_flutter_ios_sdk9_objc +#endif + +/// Non-test implementation of FGMAssetProvider, wrapping a Flutter plugin registrar. +class DefaultAssetProvider: NSObject, FGMAssetProvider { + weak var registrar: FlutterPluginRegistrar? + + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + super.init() + } + + func lookupKey(forAsset asset: String) -> String? { + return registrar?.lookupKey(forAsset: asset) + } + + func lookupKey(forAsset asset: String, fromPackage package: String) -> String? { + return registrar?.lookupKey(forAsset: asset, fromPackage: package) + } + + func imageNamed(_ name: String) -> UIImage? { + return UIImage(named: name) + } +} + +/// Non-test implementation of FGMMapEventDelegate, wrapping a FGMMapsCallbackApi instance. +class DefaultMapEventHandler: NSObject, FGMMapEventDelegate { + let callbackHandler: FGMMapsCallbackApi + + init(callbackHandler: FGMMapsCallbackApi) { + self.callbackHandler = callbackHandler + super.init() + } + + func didStartCameraMove() { + callbackHandler.didStartCameraMove { _ in } + } + + func didMoveCamera(to cameraPosition: FGMPlatformCameraPosition) { + callbackHandler.didMoveCamera(to: cameraPosition) { _ in } + } + + func didIdleCamera() { + callbackHandler.didIdleCamera { _ in } + } + + func didTap(atPosition position: FGMPlatformLatLng) { + callbackHandler.didTap(atPosition: position) { _ in } + } + + func didLongPress(atPosition position: FGMPlatformLatLng) { + callbackHandler.didLongPress(atPosition: position) { _ in } + } + + func didTapMarker(withIdentifier markerId: String) { + callbackHandler.didTapMarker(withIdentifier: markerId) { _ in } + } + + func didStartDragForMarker( + withIdentifier markerId: String, atPosition position: FGMPlatformLatLng + ) { + callbackHandler.didStartDragForMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didDragMarker(withIdentifier markerId: String, atPosition position: FGMPlatformLatLng) { + callbackHandler.didDragMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didEndDragForMarker(withIdentifier markerId: String, atPosition position: FGMPlatformLatLng) + { + callbackHandler.didEndDragForMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didTapInfoWindowOfMarker(withIdentifier markerId: String) { + callbackHandler.didTapInfoWindowOfMarker(withIdentifier: markerId) { _ in } + } + + func didTapCircle(withIdentifier circleId: String) { + callbackHandler.didTapCircle(withIdentifier: circleId) { _ in } + } + + func didTap(_ cluster: FGMPlatformCluster) { + callbackHandler.didTap(cluster) { _ in } + } + + func didTapPolygon(withIdentifier polygonId: String) { + callbackHandler.didTapPolygon(withIdentifier: polygonId) { _ in } + } + + func didTapPolyline(withIdentifier polylineId: String) { + callbackHandler.didTapPolyline(withIdentifier: polylineId) { _ in } + } + + func didTapGroundOverlay(withIdentifier groundOverlayId: String) { + callbackHandler.didTapGroundOverlay(withIdentifier: groundOverlayId) { _ in } + } +} + +public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformView { + /// The Google Maps SDK map view managed by this controller. + let mapView: GMSMapView + /// The Pigeon callback API implementation, used to send events to the Dart side. + let dartCallbackHandler: FGMMapsCallbackApi + /// The map SDK event handler, which routes events to the Dart callback handler. + let mapEventHandler: DefaultMapEventHandler + /// The main Pigeon API implementation, separate to avoid lifetime extension. + let callHandler: MapCallHandler + /// The inspector API implementation, separate to avoid lifetime extension. + let inspector: MapInspector + /// A shim to pass tile requests to `dartCallbackHandler`. This is a separate object to avoid init ordering issues. + private let tileProvider: ConcreteTileProvider + /// Whether to send notifications about camera position changes to Dart. + var trackCameraPosition = false + + /// Sub-controllers for managing individual map features. + let clusterManagersController: FGMClusterManagersController + let markersController: FGMMarkersController + let polygonsController: FGMPolygonsController + let polylinesController: FGMPolylinesController + let circlesController: FGMCirclesController + let heatmapsController: FGMHeatmapsController + let tileOverlaysController: FGMTileOverlaysController + let groundOverlaysController: FGMGroundOverlaysController + + // The resulting error message, if any, from the last attempt to set the map style. + // This is used to provide access to errors after the fact, since the map style is generally set at + // creation time and there's no mechanism to return non-fatal error details during platform view + // initialization. + var styleError: String? + /// Whether we are currently observing the "frame" key path on `mapView`. + private var isObservingFrame = false + + public convenience init( + frame: CGRect, + viewIdentifier viewId: Int64, + creationParameters: FGMPlatformMapViewCreationParams, + registrar: FlutterPluginRegistrar + ) { + let camera = FGMGetCameraPositionForPigeonCameraPosition( + creationParameters.initialCameraPosition) + + let options = GMSMapViewOptions() + options.frame = frame + options.camera = camera + if let mapId = creationParameters.mapConfiguration.mapId, !mapId.isEmpty { + options.mapID = GMSMapID(identifier: mapId) + } + + self.init( + mapView: GMSMapView(options: options), + viewIdentifier: viewId, + creationParameters: creationParameters, + assetProvider: DefaultAssetProvider(registrar: registrar), + binaryMessenger: registrar.messenger() + ) + } + + public init( + mapView: GMSMapView, + viewIdentifier viewId: Int64, + creationParameters: FGMPlatformMapViewCreationParams, + assetProvider: FGMAssetProvider, + binaryMessenger: FlutterBinaryMessenger + ) { + self.mapView = mapView + mapView.accessibilityElementsHidden = false + mapView.paddingAdjustmentBehavior = .never + // The code below must be kept in sync with `interpretMapConfiguration`. The small amount of + // duplication here is to avoid having to defer all map view configuration until after the + // sub-controllers are given the map view. + let (styleUpdateAttempted, errorString) = GoogleMapController.updateMapView( + mapView, fromConfiguration: creationParameters.mapConfiguration) + if styleUpdateAttempted { + styleError = errorString + } + if let trackCameraPosition = creationParameters.mapConfiguration.trackCameraPosition { + self.trackCameraPosition = trackCameraPosition.boolValue + } + // End duplicate code. + + let pigeonSuffix = String(format: "%lld", viewId) + dartCallbackHandler = FGMMapsCallbackApi( + binaryMessenger: binaryMessenger, + messageChannelSuffix: pigeonSuffix + ) + + mapEventHandler = DefaultMapEventHandler(callbackHandler: dartCallbackHandler) + + let markerType = creationParameters.mapConfiguration.markerType + + clusterManagersController = FGMClusterManagersController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + markersController = FGMMarkersController( + mapView: mapView, + eventDelegate: mapEventHandler, + clusterManagersController: clusterManagersController, + assetProvider: assetProvider, + markerType: markerType + ) + polygonsController = FGMPolygonsController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + polylinesController = FGMPolylinesController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + circlesController = FGMCirclesController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + heatmapsController = FGMHeatmapsController(mapView: mapView) + tileProvider = ConcreteTileProvider(dartCallbackHandler: dartCallbackHandler) + tileOverlaysController = FGMTileOverlaysController( + mapView: mapView, + tileProvider: tileProvider + ) + groundOverlaysController = FGMGroundOverlaysController( + mapView: mapView, + eventDelegate: mapEventHandler, + assetProvider: assetProvider + ) + + clusterManagersController.add(creationParameters.initialClusterManagers) + markersController.add(creationParameters.initialMarkers) + polygonsController.add(creationParameters.initialPolygons) + polylinesController.add(creationParameters.initialPolylines) + circlesController.add(creationParameters.initialCircles) + heatmapsController.add(creationParameters.initialHeatmaps) + tileOverlaysController.add(creationParameters.initialTileOverlays) + groundOverlaysController.add(creationParameters.initialGroundOverlays) + + callHandler = MapCallHandler( + messenger: binaryMessenger, + pigeonSuffix: pigeonSuffix + ) + inspector = MapInspector( + messenger: binaryMessenger, + pigeonSuffix: pigeonSuffix + ) + + super.init() + + callHandler.controller = self + SetUpFGMMapsApiWithSuffix(binaryMessenger, callHandler, pigeonSuffix) + inspector.controller = self + SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, inspector, pigeonSuffix) + + mapView.delegate = self + isObservingFrame = true + mapView.addObserver(self, forKeyPath: "frame", options: [], context: nil) + + // Invoke clustering after everything is configured. + clusterManagersController.invokeClusteringForEachClusterManager() + } + + deinit { + if isObservingFrame { + mapView.removeObserver(self, forKeyPath: "frame") + } + SetUpFGMMapsApiWithSuffix(callHandler.messenger, nil, callHandler.pigeonSuffix) + SetUpFGMMapsInspectorApiWithSuffix(inspector.messenger, nil, inspector.pigeonSuffix) + } + + public func view() -> UIView { + return mapView + } + + override public func observeValue( + forKeyPath keyPath: String?, + of object: Any?, + change: [NSKeyValueChangeKey: Any]?, + context: UnsafeMutableRawPointer? + ) { + if let keyPath = keyPath, + let gmsMapView = object as? GMSMapView, + gmsMapView == mapView, + keyPath == "frame" + { + let bounds = mapView.bounds + if bounds.equalTo(.zero) { + // The workaround is to fix an issue that the camera location is not current when + // the size of the map is zero at initialization. + // So We only care about the size of the `self.mapView`, ignore the frame changes when the + // size is zero. + return + } + // We only observe the frame for initial setup. + isObservingFrame = false + mapView.removeObserver(self, forKeyPath: "frame") + mapView.moveCamera(GMSCameraUpdate.setCamera(mapView.camera)) + } else { + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + } + } + + public func showAtOrigin(_ origin: CGPoint) { + mapView.frame = CGRect(origin: origin, size: mapView.frame.size) + mapView.isHidden = false + } + + public func hide() { + mapView.isHidden = true + } + + public func cameraPosition() -> GMSCameraPosition? { + return trackCameraPosition ? mapView.camera : nil + } + + func setCamera(_ camera: GMSCameraPosition) { + mapView.camera = camera + } + + /// Sets the map style, returning any error string as well as storing that error in `styleError` for + /// later access. + func setMapStyle(_ mapStyle: String) -> String? { + let (style, errorString) = GoogleMapController.parseMapStyle(mapStyle) + if errorString == nil { + mapView.mapStyle = style + } + styleError = errorString + return errorString + } + + /// Attempts to construct a GMSMapStyle from a JSON style string, returning the style, as well as + /// an error string if it the style could not be created. + /// + /// - If the String? value is non-nil, that description of the error should be stored in + /// `styleError` by the caller for later access, and the style should be set on the map. + /// - If the String? value is nil, the style should be set on the map. The style may be nil if + /// the input string is empty, which is how the platform channel expresses clearing the style. + static func parseMapStyle(_ jsonStyle: String) -> (GMSMapStyle?, String?) { + if jsonStyle.isEmpty { + return (nil, nil) + } + do { + let style = try GMSMapStyle(jsonString: jsonStyle) + return (style, nil) + } catch let error { + return (nil, error.localizedDescription) + } + } + + // MARK: - GMSMapViewDelegate methods + + public func mapView(_ mapView: GMSMapView, willMove gesture: Bool) { + mapEventHandler.didStartCameraMove() + } + + public func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { + if trackCameraPosition { + mapEventHandler.didMoveCamera(to: FGMGetPigeonCameraPositionForPosition(position)) + } + } + + public func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) { + mapEventHandler.didIdleCamera() + } + + public func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { + if let cluster = marker.userData as? GMUStaticCluster { + clusterManagersController.didTap(cluster) + return false + } + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + return markersController.didTapMarker(withIdentifier: markerId) + } + return false + } + + public func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didEndDraggingMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didStartDraggingMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didDragMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didTapInfoWindowOfMarker(withIdentifier: markerId) + } + } + + public func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) { + guard let userDataArray = overlay.userData as? [Any], + let overlayId = userDataArray.first as? String + else { + return + } + if polylinesController.hasPolyline(withIdentifier: overlayId) == true { + polylinesController.didTapPolyline(withIdentifier: overlayId) + } else if polygonsController.hasPolygon(withIdentifier: overlayId) == true { + polygonsController.didTapPolygon(withIdentifier: overlayId) + } else if circlesController.hasCircle(withIdentifier: overlayId) == true { + circlesController.didTapCircle(withIdentifier: overlayId) + } else if groundOverlaysController.hasGroundOverlays(withIdentifier: overlayId) == true { + groundOverlaysController.didTapGroundOverlay(withIdentifier: overlayId) + } + } + + public func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) { + mapEventHandler.didTap(atPosition: FGMGetPigeonLatLngForCoordinate(coordinate)) + } + + public func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) { + mapEventHandler.didLongPress(atPosition: FGMGetPigeonLatLngForCoordinate(coordinate)) + } + + func interpretMapConfiguration(_ config: FGMPlatformMapConfiguration) { + // Any changes here must also be made to the `init` method above. See the comment there for + // details. + let (styleUpdateAttempted, errorString) = GoogleMapController.updateMapView( + mapView, fromConfiguration: config) + if styleUpdateAttempted { + styleError = errorString + } + if let trackCameraPosition = config.trackCameraPosition { + self.trackCameraPosition = trackCameraPosition.boolValue + } + } + + /// Updates the given map view with new configuration options. + /// + /// Returns a boolean indicating whether a style update was attempted, and an error string + /// describing any error interpreting the style in `config`. If the boolean is true, the error + /// string should be stored in `styleError` for later access. + static func updateMapView( + _ mapView: GMSMapView, fromConfiguration config: FGMPlatformMapConfiguration + ) -> (Bool, String?) { + if let cameraTargetBounds = config.cameraTargetBounds { + if let bounds = cameraTargetBounds.bounds { + mapView.cameraTargetBounds = FGMGetCoordinateBoundsForPigeonLatLngBounds(bounds) + } else { + mapView.cameraTargetBounds = nil + } + } + if let compassEnabled = config.compassEnabled { + mapView.settings.compassButton = compassEnabled.boolValue + } + if let indoorEnabled = config.indoorViewEnabled { + mapView.isIndoorEnabled = indoorEnabled.boolValue + } + if let trafficEnabled = config.trafficEnabled { + mapView.isTrafficEnabled = trafficEnabled.boolValue + } + if let buildingsEnabled = config.buildingsEnabled { + mapView.isBuildingsEnabled = buildingsEnabled.boolValue + } + if let mapType = config.mapType { + mapView.mapType = FGMGetMapViewTypeForPigeonMapType(mapType.value) + } + if let zoomData = config.minMaxZoomPreference { + let minZoom = zoomData.min?.floatValue ?? kGMSMinZoomLevel + let maxZoom = zoomData.max?.floatValue ?? kGMSMaxZoomLevel + mapView.setMinZoom(minZoom, maxZoom: maxZoom) + } + if let padding = config.padding { + mapView.padding = UIEdgeInsets( + top: CGFloat(padding.top), + left: CGFloat(padding.left), + bottom: CGFloat(padding.bottom), + right: CGFloat(padding.right) + ) + } + if let rotateGesturesEnabled = config.rotateGesturesEnabled { + mapView.settings.rotateGestures = rotateGesturesEnabled.boolValue + } + if let scrollGesturesEnabled = config.scrollGesturesEnabled { + mapView.settings.scrollGestures = scrollGesturesEnabled.boolValue + } + if let tiltGesturesEnabled = config.tiltGesturesEnabled { + mapView.settings.tiltGestures = tiltGesturesEnabled.boolValue + } + if let zoomGesturesEnabled = config.zoomGesturesEnabled { + mapView.settings.zoomGestures = zoomGesturesEnabled.boolValue + } + if let myLocationEnabled = config.myLocationEnabled { + mapView.isMyLocationEnabled = myLocationEnabled.boolValue + } + if let myLocationButtonEnabled = config.myLocationButtonEnabled { + mapView.settings.myLocationButton = myLocationButtonEnabled.boolValue + } + if let mapStyle = config.style { + let (style, errorString) = GoogleMapController.parseMapStyle(mapStyle) + if errorString == nil { + mapView.mapStyle = style + } + return (true, errorString) + } + return (false, nil) + } +} + +// TODO(stuartmorgan): Remove this in favor of an extension to add FGMTileProviderDelegate to +// the Pigeon Flutter API object once this plugin has switched to Swift Pigeon generation +// (adjusting the protocol to match the Swift version of the signature). +private class ConcreteTileProvider: NSObject, FGMTileProviderDelegate { + let handler: FGMMapsCallbackApi + + init(dartCallbackHandler: FGMMapsCallbackApi) { + handler = dartCallbackHandler + } + + public func tile( + withOverlayIdentifier tileOverlayId: String, + location: FGMPlatformPoint, + zoom: Int, + completion: @escaping (FGMPlatformTile?, FlutterError?) -> Void + ) { + handler.tile( + withOverlayIdentifier: tileOverlayId, + location: location, + zoom: zoom, + completion: completion + ) + } +} + +class MapCallHandler: NSObject, FGMMapsApi { + weak var controller: GoogleMapController? + let messenger: FlutterBinaryMessenger + let pigeonSuffix: String + var transactionWrapper: FGMCATransactionProtocol + + init( + messenger: FlutterBinaryMessenger, + pigeonSuffix suffix: String + ) { + self.messenger = messenger + self.pigeonSuffix = suffix + self.transactionWrapper = FGMCATransactionWrapper() + super.init() + } + + func waitForMapWithError(_ error: AutoreleasingUnsafeMutablePointer) { + // No-op; this call just ensures synchronization with the platform thread. + } + + func updateCircles( + byAdding toAdd: [FGMPlatformCircle], changing toChange: [FGMPlatformCircle], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.circlesController.add(toAdd) + controller?.circlesController.change(toChange) + controller?.circlesController.removeCircles(withIdentifiers: idsToRemove) + } + + func updateHeatmaps( + byAdding toAdd: [FGMPlatformHeatmap], changing toChange: [FGMPlatformHeatmap], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.heatmapsController.add(toAdd) + controller?.heatmapsController.change(toChange) + controller?.heatmapsController.removeHeatmaps(withIdentifiers: idsToRemove) + } + + func update( + with configuration: FGMPlatformMapConfiguration, + error: AutoreleasingUnsafeMutablePointer + ) { + controller?.interpretMapConfiguration(configuration) + } + + func updateMarkers( + byAdding toAdd: [FGMPlatformMarker], changing toChange: [FGMPlatformMarker], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.add(toAdd) + controller?.markersController.change(toChange) + controller?.markersController.removeMarkers(withIdentifiers: idsToRemove) + controller?.clusterManagersController.invokeClusteringForEachClusterManager() + } + + func updateClusterManagers( + byAdding toAdd: [FGMPlatformClusterManager], removing idsToRemove: [String], + error: AutoreleasingUnsafeMutablePointer + ) { + controller?.clusterManagersController.add(toAdd) + controller?.clusterManagersController.removeClusterManagers(withIdentifiers: idsToRemove) + } + + func updatePolygons( + byAdding toAdd: [FGMPlatformPolygon], changing toChange: [FGMPlatformPolygon], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.polygonsController.add(toAdd) + controller?.polygonsController.change(toChange) + controller?.polygonsController.removePolygon(withIdentifiers: idsToRemove) + } + + func updatePolylines( + byAdding toAdd: [FGMPlatformPolyline], changing toChange: [FGMPlatformPolyline], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.polylinesController.add(toAdd) + controller?.polylinesController.change(toChange) + controller?.polylinesController.removePolyline(withIdentifiers: idsToRemove) + } + + func updateTileOverlays( + byAdding toAdd: [FGMPlatformTileOverlay], changing toChange: [FGMPlatformTileOverlay], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.tileOverlaysController.add(toAdd) + controller?.tileOverlaysController.change(toChange) + controller?.tileOverlaysController.removeTileOverlay(withIdentifiers: idsToRemove) + } + + func updateGroundOverlays( + byAdding toAdd: [FGMPlatformGroundOverlay], changing toChange: [FGMPlatformGroundOverlay], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.groundOverlaysController.add(toAdd) + controller?.groundOverlaysController.change(toChange) + controller?.groundOverlaysController.removeGroundOverlays(withIdentifiers: idsToRemove) + } + + func latLng( + forScreenCoordinate screenCoordinate: FGMPlatformPoint, + error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformLatLng? { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getLatLng called prior to map initialization", + details: nil + ) + return nil + } + let point = FGMGetCGPointForPigeonPoint(screenCoordinate) + let latlng = mapView.projection.coordinate(for: point) + return FGMGetPigeonLatLngForCoordinate(latlng) + } + + func screenCoordinates( + for latLng: FGMPlatformLatLng, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformPoint? { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getScreenCoordinate called prior to map initialization", + details: nil + ) + return nil + } + let location = FGMGetCoordinateForPigeonLatLng(latLng) + let point = mapView.projection.point(for: location) + return FGMGetPigeonPointForCGPoint(point) + } + + func visibleMapRegion(_ error: AutoreleasingUnsafeMutablePointer) + -> FGMPlatformLatLngBounds? + { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getVisibleRegion called prior to map initialization", + details: nil + ) + return nil + } + let visibleRegion = mapView.projection.visibleRegion() + let bounds = GMSCoordinateBounds(region: visibleRegion) + return FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds) + } + + func moveCamera( + with cameraUpdate: FGMPlatformCameraUpdate, + error: AutoreleasingUnsafeMutablePointer + ) { + guard let update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate) else { + error.pointee = FlutterError( + code: "Invalid update", + message: "Unrecognized camera update", + details: nil + ) + return + } + controller?.mapView.moveCamera(update) + } + + func animateCamera( + with cameraUpdate: FGMPlatformCameraUpdate, duration durationMilliseconds: NSNumber?, + error: AutoreleasingUnsafeMutablePointer + ) { + guard let update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate) else { + error.pointee = FlutterError( + code: "Invalid update", + message: "Unrecognized camera update", + details: nil + ) + return + } + let transaction = durationMilliseconds != nil ? transactionWrapper : nil + transaction?.begin() + if let duration = durationMilliseconds { + transaction?.setAnimationDuration(duration.doubleValue / 1000.0) + } + controller?.mapView.animate(with: update) + transaction?.commit() + } + + func currentZoomLevel(_ error: AutoreleasingUnsafeMutablePointer) -> NSNumber? { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.camera.zoom) + } + + func showInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.showMarkerInfoWindow(withIdentifier: markerId, error: error) + } + + func hideInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.hideMarkerInfoWindow(withIdentifier: markerId, error: error) + } + + func isShowingInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) -> NSNumber? { + return controller?.markersController.isInfoWindowShownForMarker( + withIdentifier: markerId, error: error) + } + + func setStyle(_ style: String, error: AutoreleasingUnsafeMutablePointer) -> String? + { + return controller?.setMapStyle(style) + } + + func lastStyleError(_ error: AutoreleasingUnsafeMutablePointer) -> String? { + return controller?.styleError + } + + func clearTileCacheForOverlay( + withIdentifier tileOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.tileOverlaysController.clearTileCache(withIdentifier: tileOverlayId) + } + + func takeSnapshotWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> FlutterStandardTypedData? + { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "takeSnapshot called prior to map initialization", + details: nil + ) + return nil + } + let renderer = UIGraphicsImageRenderer(size: mapView.bounds.size) + let image = renderer.image { context in + mapView.drawHierarchy(in: mapView.bounds, afterScreenUpdates: true) + } + if let imageData = image.pngData() { + return FlutterStandardTypedData(bytes: imageData) + } + return nil + } + + func isAdvancedMarkersAvailable(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return false + } + return NSNumber(value: mapView.mapCapabilities.contains(.advancedMarkers)) + } +} + +class MapInspector: NSObject, FGMMapsInspectorApi { + weak var controller: GoogleMapController? + let messenger: FlutterBinaryMessenger + let pigeonSuffix: String + + init( + messenger: FlutterBinaryMessenger, + pigeonSuffix suffix: String + ) { + self.messenger = messenger + self.pigeonSuffix = suffix + super.init() + } + + func areBuildingsEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.isBuildingsEnabled) + } + + func areRotateGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.rotateGestures) + } + + func areScrollGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.scrollGestures) + } + + func areTiltGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.tiltGestures) + } + + func areZoomGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.zoomGestures) + } + + func tileOverlay( + withIdentifier tileOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformTileLayer? { + guard let controller = controller, + let layer = controller.tileOverlaysController.tileOverlay(withIdentifier: tileOverlayId)? + .layer + else { + return nil + } + return FGMPlatformTileLayer.make( + withVisible: layer.map != nil, + fadeIn: layer.fadeIn, + opacity: Double(layer.opacity), + zIndex: Int(layer.zIndex) + ) + } + + func heatmap( + withIdentifier heatmapId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformHeatmap? { + return controller?.heatmapsController.heatmap(withIdentifier: heatmapId) + } + + func clusters( + withIdentifier clusterManagerId: String, error: AutoreleasingUnsafeMutablePointer + ) -> [FGMPlatformCluster]? { + return controller?.clusterManagersController.clusters( + withIdentifier: clusterManagerId, error: error) + } + + func isCompassEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.compassButton) + } + + func isMyLocationButtonEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.myLocationButton) + } + + func isTrafficEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.isTrafficEnabled) + } + + func zoomRange(_ error: AutoreleasingUnsafeMutablePointer) -> FGMPlatformZoomRange? + { + guard let mapView = controller?.mapView else { + return nil + } + return FGMPlatformZoomRange.make( + withMin: NSNumber(value: mapView.minZoom), + max: NSNumber(value: mapView.maxZoom) + ) + } + + func groundOverlay( + withIdentifier groundOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformGroundOverlay? { + return controller?.groundOverlaysController.groundOverlay(withIdentifier: groundOverlayId) + } + + func cameraPosition(_ error: AutoreleasingUnsafeMutablePointer) + -> FGMPlatformCameraPosition? + { + guard let mapView = controller?.mapView else { + return nil + } + return FGMGetPigeonCameraPositionForPosition(mapView.camera) + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapFactory.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapFactory.swift new file mode 100644 index 000000000000..bbd27c27ee46 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapFactory.swift @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps + +#if canImport(google_maps_flutter_ios_sdk9_objc) + import google_maps_flutter_ios_sdk9_objc +#endif + +class GoogleMapFactory: NSObject, FlutterPlatformViewFactory { + weak var registrar: FlutterPluginRegistrar? + static var sharedMapServices = GMSServices.sharedServices() + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + } + + func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) + -> any FlutterPlatformView + { + // Precache shared map services, if needed. Initializing this prepares GMSServices + // on a background thread controlled by the GoogleMaps framework. + _ = GoogleMapFactory.sharedMapServices + + return GoogleMapController( + frame: frame, viewIdentifier: viewId, + creationParameters: args as! FGMPlatformMapViewCreationParams, registrar: registrar!) + } + + func createArgsCodec() -> any FlutterMessageCodec & NSObjectProtocol { + return FGMGetGoogleMapsFlutterPigeonMessagesCodec() + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapsPlugin.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapsPlugin.swift new file mode 100644 index 000000000000..8ca573ad6d9f --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/GoogleMapsPlugin.swift @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps + +public class GoogleMapsPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let factory = GoogleMapFactory(registrar: registrar) + registrar.register( + factory, + withId: "plugins.flutter.dev/google_maps_ios", + gestureRecognizersBlockingPolicy: + FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded) + GMSServices.addInternalUsageAttributionID("gmp_flutter_googlemapsflutter_ios") + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapController.h deleted file mode 100644 index b723c8d3658e..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapController.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMCATransactionWrapper.h" -#import "FGMCircleController.h" -#import "FGMClusterManagersController.h" -#import "FGMMarkerController.h" -#import "FGMPolygonController.h" -#import "FGMPolylineController.h" -#import "google_maps_flutter_pigeon_messages.g.h" - -NS_ASSUME_NONNULL_BEGIN - -// Defines map overlay controllable from Flutter. -@interface FGMGoogleMapController : NSObject -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *)registrar; -- (void)showAtOrigin:(CGPoint)origin; -- (void)hide; -- (nullable GMSCameraPosition *)cameraPosition; -@end - -// Allows the engine to create new Google Map instances. -@interface FGMGoogleMapFactory : NSObject -- (instancetype)initWithRegistrar:(NSObject *)registrar; -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapController_Test.h deleted file mode 100644 index 5e1fa9371b2c..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapController_Test.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMAssetProvider.h" -#import "FGMCATransactionWrapper.h" -#import "FGMGoogleMapController.h" - -NS_ASSUME_NONNULL_BEGIN - -/// Implementation of the Pigeon maps API. -/// -/// This is a separate object from the maps controller because the Pigeon API registration keeps a -/// strong reference to the implementor, but as the FlutterPlatformView, the lifetime of the -/// FGMGoogleMapController instance is what needs to trigger Pigeon unregistration, so can't be -/// the target of the registration. -@interface FGMMapCallHandler : NSObject - -/// The transaction wrapper to use for camera animations. -@property(nonatomic, strong) id transactionWrapper; - -@end - -/// Implementation of the Pigeon maps inspector API. -/// -/// This is a separate object from the maps controller because the Pigeon API registration keeps a -/// strong reference to the implementor, but as the FlutterPlatformView, the lifetime of the -/// FGMGoogleMapController instance is what needs to trigger Pigeon unregistration, so can't be -/// the target of the registration. -@interface FGMMapInspector : NSObject - -/// Initializes a Pigeon API for inpector with a map controller. -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix; - -@end - -@interface FGMGoogleMapController (Test) - -/// Initializes a map controller with a concrete map view. -/// -/// @param mapView A map view that will be displayed by the controller -/// @param viewId A unique identifier for the controller. -/// @param creationParameters Parameters for initialising the map view. -/// @param assetProvider The asset provider to use for looking up assets. -/// @param binaryMessenger The binary messenger to use for sending messages to Dart. -- (instancetype)initWithMapView:(GMSMapView *)mapView - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - assetProvider:(NSObject *)assetProvider - binaryMessenger:(NSObject *)binaryMessenger; - -// The main Pigeon API implementation. -@property(nonatomic, strong, readonly) FGMMapCallHandler *callHandler; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapsPlugin.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapsPlugin.h deleted file mode 100644 index ec294eb3d3e9..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGoogleMapsPlugin.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMCircleController.h" -#import "FGMClusterManagersController.h" -#import "FGMGoogleMapController.h" -#import "FGMMarkerController.h" -#import "FGMPolygonController.h" -#import "FGMPolylineController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FGMGoogleMapsPlugin : NSObject -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMCATransactionWrapper.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMCATransactionWrapper.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMCATransactionWrapper.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMCATransactionWrapper.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMCircleController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMCircleController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMCircleController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMCircleController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMClusterManagersController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMClusterManagersController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMClusterManagersController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMClusterManagersController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMConversionUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMConversionUtils.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMConversionUtils.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMConversionUtils.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGroundOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMGroundOverlayController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMGroundOverlayController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMGroundOverlayController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMHeatmapController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMHeatmapController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMHeatmapController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMHeatmapController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMImageUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMImageUtils.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMImageUtils.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMImageUtils.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMMarkerController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMMarkerController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMMarkerController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMMarkerController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMMarkerUserData.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMMarkerUserData.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMMarkerUserData.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMMarkerUserData.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMPolygonController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMPolygonController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMPolygonController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMPolygonController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMPolylineController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMPolylineController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMPolylineController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMTileOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMTileOverlayController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/FGMTileOverlayController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/FGMTileOverlayController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/Resources/PrivacyInfo.xcprivacy b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/Resources/PrivacyInfo.xcprivacy similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/Resources/PrivacyInfo.xcprivacy rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/Resources/PrivacyInfo.xcprivacy diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/google_maps_flutter_pigeon_messages.g.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/google_maps_flutter_pigeon_messages.g.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/google_maps_flutter_pigeon_messages.g.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/google_maps_flutter_pigeon_messages.g.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMAssetProvider.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMAssetProvider.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMAssetProvider.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMAssetProvider.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMCATransactionWrapper.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMCATransactionWrapper.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMCATransactionWrapper.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMCATransactionWrapper.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMCircleController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMCircleController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMCircleController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMCircleController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMCircleController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMCircleController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMCircleController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMCircleController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMClusterManagersController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMClusterManagersController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMClusterManagersController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMClusterManagersController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMConversionUtils.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMConversionUtils.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMConversionUtils.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMConversionUtils.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGroundOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMGroundOverlayController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGroundOverlayController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMGroundOverlayController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGroundOverlayController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMGroundOverlayController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMGroundOverlayController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMGroundOverlayController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMHeatmapController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMHeatmapController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMHeatmapController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMHeatmapController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMHeatmapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMHeatmapController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMHeatmapController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMHeatmapController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMImageUtils.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMImageUtils.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMImageUtils.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMImageUtils.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMapEventDelegate.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMapEventDelegate.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMapEventDelegate.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMapEventDelegate.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMarkerController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMarkerController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMarkerController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMarkerController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMarkerController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMarkerController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMarkerController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMarkerController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMarkerUserData.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMarkerUserData.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMMarkerUserData.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMMarkerUserData.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolygonController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolygonController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolygonController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolygonController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolygonController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolygonController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolygonController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolygonController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolylineController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolylineController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolylineController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolylineController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolylineController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMPolylineController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMPolylineController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMTileOverlayController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMTileOverlayController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMTileOverlayController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMTileOverlayController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMTileOverlayController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/FGMTileOverlayController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/FGMTileOverlayController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/GoogleMapsUtilsTrampoline.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/GoogleMapsUtilsTrampoline.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/GoogleMapsUtilsTrampoline.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/GoogleMapsUtilsTrampoline.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/google_maps_flutter_pigeon_messages.g.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/google_maps_flutter_pigeon_messages.g.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/google_maps_flutter_pigeon_messages.g.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk10/ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/google_maps_flutter_pigeon_messages.g.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/pubspec.yaml index f50b68394747..dbf39b90f41e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_ios_sdk10 description: iOS implementation of the google_maps_flutter plugin using Google Maps SDK 10. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios_sdk10 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.18.5 +version: 2.18.6 environment: sdk: ^3.10.0 @@ -13,7 +13,7 @@ flutter: implements: google_maps_flutter platforms: ios: - pluginClass: FGMGoogleMapsPlugin + pluginClass: GoogleMapsPlugin dartPluginClass: GoogleMapsFlutterIOS dependencies: diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/sync_shared_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/sync_shared_files.dart index 8711068a5604..5fc97464adb5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/sync_shared_files.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/sync_shared_files.dart @@ -33,7 +33,7 @@ void _syncSharedFiles(Directory packageRoot, String packageName, Directory share .map((e) => p.basename(e.path)) .where( (name) => - name.startsWith('google_maps_flutter_ios') && + name.startsWith('google_maps_flutter_ios_') && name != _sharedSourceRootName && name != packageName, ) @@ -116,8 +116,9 @@ void _syncFile(File source, String destinationPath, String destinationPackageNam ].any((pattern) => source.absolute.path.contains(pattern))) { updatePackageNameInPathReferences(File(destinationPath), destinationPackageName); } - // Native unit tests need to import the Swift package. - if (source.absolute.path.contains('/RunnerTests/')) { + // Native unit tests need to import the Swift package, and the Swift files need to import the + // Obj-C sub-package until the Swift migration is complete. + if (source.absolute.path.contains('/RunnerTests/') || source.absolute.path.endsWith('.swift')) { updatePackageNameInImports(File(destinationPath), destinationPackageName); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/unshared_source_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/unshared_source_files.dart index dee386df465d..fb0eab0fb288 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/unshared_source_files.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/unshared_source_files.dart @@ -13,5 +13,5 @@ const intentionallyUnsharedSourceFiles = [ // Each package will have its own list. 'tool/unshared_source_files.dart', // Unshared due to https://github.com/flutter/flutter/issues/183441. - 'ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10/include/google_maps_flutter_ios_sdk10/GoogleMapsUtilsTrampoline.h', + 'ios/google_maps_flutter_ios_sdk10/Sources/google_maps_flutter_ios_sdk10_objc/include/google_maps_flutter_ios_sdk10_objc/GoogleMapsUtilsTrampoline.h', ]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/utils.dart b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/utils.dart index 3fb80a0b7e64..2508a25c786a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/utils.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk10/tool/utils.dart @@ -49,9 +49,9 @@ List unexpectedUnsharedSourceFiles( /// Adjusts a package-relative path to account for the package name being part of /// the directory structure for Swift packages. String sharedSourceRelativePathForPackagePath(String packageRelativePath) { - return packageRelativePath.replaceAll( - RegExp(r'/google_maps_flutter_ios[_\w\d]*/'), - '/google_maps_flutter_ios/', + return packageRelativePath.replaceAllMapped( + RegExp(r'/google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?)/'), + (match) => '/google_maps_flutter_ios${match.group(1)}/', ); } @@ -61,7 +61,10 @@ String packageRelativePathForSharedSourceRelativePath( String packageName, String sharedSourceRelativePath, ) { - return sharedSourceRelativePath.replaceAll('/google_maps_flutter_ios/', '/$packageName/'); + return sharedSourceRelativePath.replaceAllMapped( + RegExp(r'/google_maps_flutter_ios((?:_objc)?)/'), + (match) => '/$packageName${match.group(1)}/', + ); } /// Returns the contents of the file with any differences caused only by the @@ -70,7 +73,8 @@ String normalizedFileContents(File file) { return file .readAsStringSync() // Ignore differences caused only by the package name. - .replaceAll(RegExp(r'google_maps_flutter_ios_[\w\d]+'), 'google_maps_flutter_ios') + .replaceAll(RegExp(r'google_maps_flutter_ios_sdk[\d]+'), 'google_maps_flutter_ios') + .replaceAll(RegExp(r'google_maps_flutter_ios_sdk[\d]+_objc'), 'google_maps_flutter_ios_objc') // Package name diffs could change line wrapping, so collapse whitespace. .replaceAll(RegExp(r'[\s\n]+'), ' ') .trim(); @@ -84,7 +88,7 @@ String normalizedFileContents(File file) { /// should be replaced in all files. void updatePackageNameInPathReferences(File file, String packageName) { final String newContents = file.readAsStringSync().replaceAllMapped( - RegExp(r'google_maps_flutter_ios[_\w\d]*([:/])'), + RegExp(r'google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?[:/])'), (match) => '$packageName${match.group(1)}', ); file.writeAsStringSync(newContents); @@ -100,13 +104,16 @@ void updatePackageNameInImports(File file, String packageName) { .readAsStringSync() // Package imports. .replaceAllMapped( - RegExp(r'^(@?(?:testable )?)import google_maps_flutter_ios[_\w\d]*(;?)$', multiLine: true), + RegExp( + r'^(@?(?:testable )?)import google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?;?)$', + multiLine: true, + ), (match) => '${match.group(1)}import $packageName${match.group(2)}', ) // Bridging header. .replaceAllMapped( - RegExp(r'^#import '#import <$packageName/', + RegExp(r'^#import '#import <$packageName${match.group(1)}/', ); file.writeAsStringSync(newContents); } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/CHANGELOG.md b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/CHANGELOG.md index b8e989f8c9b0..e3438e2a9166 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/CHANGELOG.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.18.7 + +* Converts parts of the implementation to Swift. + ## 2.18.6 * Fixes a potential compilation issue in tile downscaling. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/GoogleMapsTests.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/GoogleMapsTests.swift index 86be81902dfb..55b18c277577 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/GoogleMapsTests.swift +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/GoogleMapsTests.swift @@ -60,7 +60,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { @Test func plugin() { // Verify that creating an actual plugin instance succeeds. - let _ = FGMGoogleMapsPlugin() + let _ = GoogleMapsPlugin() } @Test func frameObserver() { @@ -69,7 +69,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { options.frame = frame options.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0) let mapView = PartiallyMockedMapView(options: options) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -86,20 +86,6 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { #expect(mapView.frameObserverCount == 0) } - @Test func mapsServiceSync() { - // The API requires a registrar, but this test doesn't actually use it, so just pass in a - // dummy object rather than set up a full mock. - let registrar = StubPluginRegistrar() - let factory1 = FGMGoogleMapFactory(registrar: registrar) - #expect(factory1.sharedMapServices != nil) - let factory2 = FGMGoogleMapFactory(registrar: registrar) - // Test pointer equality, should be same retained singleton +[GMSServices sharedServices] object. - // Retaining the opaque object should be enough to avoid multiple internal initializations, - // but don't test the internals of the GoogleMaps API. Assume that it does what is documented. - // https://developers.google.com/maps/documentation/ios-sdk/reference/interface_g_m_s_services#a436e03c32b1c0be74e072310a7158831 - #expect(factory1.sharedMapServices as AnyObject === factory2.sharedMapServices as AnyObject) - } - @Test func handleResultTileDownsamplesWideGamutImages() throws { let controller = FGMTileProviderController() @@ -128,7 +114,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -160,7 +146,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -200,7 +186,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) let binaryMessenger = StubBinaryMessenger() - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -208,11 +194,8 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { binaryMessenger: binaryMessenger ) - let inspector = FGMMapInspector( - mapController: controller, - messenger: binaryMessenger, - pigeonSuffix: "0" - ) + let inspector = MapInspector(messenger: binaryMessenger, pigeonSuffix: "0") + inspector.controller = controller var error: FlutterError? = nil let cameraPosition = try #require(inspector.cameraPosition(&error)) @@ -263,4 +246,67 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { initialGroundOverlays: [] ) } + + @Test func frameObserverRemovedOnDeinitIfNeverFired() { + let options = GMSMapViewOptions() + options.frame = .zero + options.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0) + let mapView = PartiallyMockedMapView(options: options) + + var controller: GoogleMapController? = GoogleMapController( + mapView: mapView, + viewIdentifier: 0, + creationParameters: emptyCreationParameters(), + assetProvider: TestAssetProvider(), + binaryMessenger: StubBinaryMessenger() + ) + + #expect(mapView.frameObserverCount == 1) + + // Deallocate the controller + controller = nil + + #expect(mapView.frameObserverCount == 0) + } + + @Test func styleErrorPersistsAcrossConfigUpdates() { + let mapView = PartiallyMockedMapView(options: GMSMapViewOptions()) + let controller = GoogleMapController( + mapView: mapView, + viewIdentifier: 0, + creationParameters: emptyCreationParameters(), + assetProvider: TestAssetProvider(), + binaryMessenger: StubBinaryMessenger() + ) + + // Set an invalid style to trigger an error + _ = controller.setMapStyle("invalid json") + #expect(controller.styleError != nil) + + // Update config without style + let config = FGMPlatformMapConfiguration.make( + withCompassEnabled: true, + cameraTargetBounds: nil, + mapType: nil, + minMaxZoomPreference: nil, + rotateGesturesEnabled: nil, + scrollGesturesEnabled: nil, + tiltGesturesEnabled: nil, + trackCameraPosition: nil, + zoomGesturesEnabled: nil, + myLocationEnabled: nil, + myLocationButtonEnabled: nil, + padding: nil, + indoorViewEnabled: nil, + trafficEnabled: nil, + buildingsEnabled: nil, + markerType: .marker, + mapId: nil, + style: nil + ) + controller.interpretMapConfiguration(config) + + // The style error should still be present + #expect(controller.styleError != nil) + } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/RunnerTests-Bridging-Header.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/RunnerTests-Bridging-Header.h index 8a24d7ee88c5..542e29ad0334 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/RunnerTests-Bridging-Header.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/example/ios/RunnerTests/RunnerTests-Bridging-Header.h @@ -3,18 +3,13 @@ // found in the LICENSE file. // Import private _Test.h headers from the plugin framework -#import -#import -#import -#import -#import -#import -#import -#import - -@interface FGMGoogleMapFactory (Test) -@property(strong, nonatomic, readonly) id sharedMapServices; -@end +#import +#import +#import +#import +#import +#import +#import @interface FGMTileProviderController (Testing) - (UIImage *)handleResultTile:(nullable UIImage *)tileImage; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9.podspec b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9.podspec index 7f45f35b59e8..b4e7b8abe4e6 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9.podspec +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9.podspec @@ -14,10 +14,10 @@ Downloaded by pub (not CocoaPods). s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios_sdk9' } s.documentation_url = 'https://pub.dev/packages/google_maps_flutter_ios_sdk9' - s.source_files = 'google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/**/*.{h,m}' - s.public_header_files = 'google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/**/*.h' + s.source_files = 'google_maps_flutter_ios_sdk9/Sources/**/*.{h,m,swift}' + s.public_header_files = 'google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/**/*.h' s.dependency 'Flutter' - s.dependency 'GoogleMaps', '~> 9.0' + s.dependency 'GoogleMaps', '~> 9.2' # Google-Maps-iOS-Utils 6.0 and 6.1.0 support GoogleMaps 9.x. The next release # was 6.1.3, which switched to GoogleMaps 10.x without a major version change. s.dependency 'Google-Maps-iOS-Utils', '>= 6.0', '<= 6.1.0' @@ -27,8 +27,8 @@ Downloaded by pub (not CocoaPods). # Find the Swift runtime when these plugins are built as libraries without `use_frameworks!` s.swift_version = '5.9' s.xcconfig = { - 'LIBRARY_SEARCH_PATHS' => '$(inherited) $(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift', - 'LD_RUNPATH_SEARCH_PATHS' => '$(inherited) /usr/lib/swift', + 'LIBRARY_SEARCH_PATHS' => '$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift', + 'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift', # To handle the difference in framework names between CocoaPods and Swift Package Manager. 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) FGM_USING_COCOAPODS=1', } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Package.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Package.swift index b77be54888cc..959d55efd801 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Package.swift +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Package.swift @@ -16,7 +16,7 @@ let package = Package( .library(name: "google-maps-flutter-ios-sdk9", targets: ["google_maps_flutter_ios_sdk9"]) ], dependencies: [ - .package(url: "https://github.com/googlemaps/ios-maps-sdk", "9.0.0"..<"10.0.0"), + .package(url: "https://github.com/googlemaps/ios-maps-sdk", "9.2.0"..<"10.0.0"), // 6.1.3+ requires SDK 10. .package(url: "https://github.com/googlemaps/google-maps-ios-utils", "6.0.0"..<"6.1.3"), ], @@ -24,6 +24,7 @@ let package = Package( .target( name: "google_maps_flutter_ios_sdk9", dependencies: [ + "google_maps_flutter_ios_sdk9_objc", .product( name: "GoogleMapsUtils", package: "google-maps-ios-utils" @@ -35,10 +36,23 @@ let package = Package( ], resources: [ .process("Resources") + ] + ), + .target( + name: "google_maps_flutter_ios_sdk9_objc", + dependencies: [ + .product( + name: "GoogleMapsUtils", + package: "google-maps-ios-utils" + ), + .product( + name: "GoogleMaps", + package: "ios-maps-sdk" + ), ], cSettings: [ - .headerSearchPath("include/google_maps_flutter_ios_sdk9") + .headerSearchPath("include/google_maps_flutter_ios_sdk9_objc") ] - ) + ), ] ) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGoogleMapController.m deleted file mode 100644 index 5f609c9b00de..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGoogleMapController.m +++ /dev/null @@ -1,997 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import GoogleMapsUtils; - -#import "FGMGoogleMapController.h" -#import "FGMGoogleMapController_Test.h" - -#import "FGMAssetProvider.h" -#import "FGMConversionUtils.h" -#import "FGMGroundOverlayController.h" -#import "FGMHeatmapController.h" -#import "FGMMarkerUserData.h" -#import "FGMTileOverlayController.h" -#import "google_maps_flutter_pigeon_messages.g.h" - -@interface FGMGoogleMapFactory () - -@property(weak, nonatomic) NSObject *registrar; -@property(strong, nonatomic, readonly) id sharedMapServices; - -@end - -@implementation FGMGoogleMapFactory - -@synthesize sharedMapServices = _sharedMapServices; - -- (instancetype)initWithRegistrar:(NSObject *)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSObject *)createArgsCodec { - return FGMGetGoogleMapsFlutterPigeonMessagesCodec(); -} - -- (NSObject *)createWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args { - // Precache shared map services, if needed. - // Retain the shared map services singleton, don't use the result for anything. - (void)[self sharedMapServices]; - - return [[FGMGoogleMapController alloc] initWithFrame:frame - viewIdentifier:viewId - creationParameters:args - registrar:self.registrar]; -} - -- (id)sharedMapServices { - if (_sharedMapServices == nil) { - // Calling this prepares GMSServices on a background thread controlled - // by the GoogleMaps framework. - // Retain the singleton to cache the initialization work across all map views. - _sharedMapServices = [GMSServices sharedServices]; - } - return _sharedMapServices; -} - -@end - -#pragma mark - - -/// Non-test implementation of FGMAssetProvider, wrapping a Flutter plugin -/// registrar. -@interface FGMDefaultAssetProvider : NSObject -@property(weak, nonatomic) NSObject *registrar; - -- (instancetype)initWithRegistrar:(NSObject *)registrar; -@end - -@implementation FGMDefaultAssetProvider - -- (instancetype)initWithRegistrar:(NSObject *)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSString *)lookupKeyForAsset:(NSString *)asset { - return [self.registrar lookupKeyForAsset:asset]; -} - -- (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package { - return [self.registrar lookupKeyForAsset:asset fromPackage:package]; -} - -- (UIImage *)imageNamed:(NSString *)name { - return [UIImage imageNamed:name]; -} - -@end - -#pragma mark - - -/// Non-test implementation of FGMAssetProvider, wrapping a FGMMapsCallbackApi -/// instance. -@interface FGMDefaultMapEventHandler : NSObject -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; - -- (instancetype)initWithCallbackHandler:(FGMMapsCallbackApi *)callbackHandler; -@end - -@implementation FGMDefaultMapEventHandler - -- (instancetype)initWithCallbackHandler:(FGMMapsCallbackApi *)callbackHandler { - self = [super init]; - if (self) { - _callbackHandler = callbackHandler; - } - return self; -} - -- (void)didStartCameraMove { - [self.callbackHandler didStartCameraMoveWithCompletion:^(FlutterError *_){ - }]; -} - -- (void)didMoveCameraToPosition:(FGMPlatformCameraPosition *)cameraPosition { - [self.callbackHandler didMoveCameraToPosition:cameraPosition - completion:^(FlutterError *_){ - }]; -} - -- (void)didIdleCamera { - [self.callbackHandler didIdleCameraWithCompletion:^(FlutterError *_){ - }]; -} - -- (void)didTapAtPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didTapAtPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didLongPressAtPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didLongPressAtPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapMarkerWithIdentifier:(NSString *)markerId { - [self.callbackHandler didTapMarkerWithIdentifier:markerId - completion:^(FlutterError *_){ - }]; -} - -- (void)didStartDragForMarkerWithIdentifier:(NSString *)markerId - atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didStartDragForMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didDragMarkerWithIdentifier:(NSString *)markerId atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didDragMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didEndDragForMarkerWithIdentifier:(NSString *)markerId - atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didEndDragForMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapInfoWindowOfMarkerWithIdentifier:(NSString *)markerId { - [self.callbackHandler didTapInfoWindowOfMarkerWithIdentifier:markerId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapCircleWithIdentifier:(NSString *)circleId { - [self.callbackHandler didTapCircleWithIdentifier:circleId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapCluster:(FGMPlatformCluster *)cluster { - [self.callbackHandler didTapCluster:cluster - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapPolygonWithIdentifier:(NSString *)polygonId { - [self.callbackHandler didTapPolygonWithIdentifier:polygonId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapPolylineWithIdentifier:(NSString *)polylineId { - [self.callbackHandler didTapPolylineWithIdentifier:polylineId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapGroundOverlayWithIdentifier:(NSString *)groundOverlayId { - [self.callbackHandler didTapGroundOverlayWithIdentifier:groundOverlayId - completion:^(FlutterError *_){ - }]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapCallHandler. -@interface FGMMapCallHandler () -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix; - -/// The map controller this inspector corresponds to. -@property(nonatomic, weak) FGMGoogleMapController *controller; -/// The messenger this instance was registered with by Pigeon. -@property(nonatomic, copy) NSObject *messenger; -/// The suffix this instance was registered under with Pigeon. -@property(nonatomic, copy) NSString *pigeonSuffix; -@end - -#pragma mark - - -/// Private declarations of the FGMMapInspector. -@interface FGMMapInspector () - -/// The map controller this inspector corresponds to. -@property(nonatomic, weak) FGMGoogleMapController *controller; -/// The messenger this instance was registered with by Pigeon. -@property(nonatomic, copy) NSObject *messenger; -/// The suffix this instance was registered under with Pigeon. -@property(nonatomic, copy) NSString *pigeonSuffix; -@end - -#pragma mark - - -@interface FGMGoogleMapController () - -@property(nonatomic, strong) GMSMapView *mapView; -@property(nonatomic, strong) FGMMapsCallbackApi *dartCallbackHandler; -@property(nonatomic, strong) FGMDefaultMapEventHandler *mapEventHandler; -@property(nonatomic, assign) BOOL trackCameraPosition; -@property(nonatomic, strong) FGMClusterManagersController *clusterManagersController; -@property(nonatomic, strong) FGMMarkersController *markersController; -@property(nonatomic, strong) FGMPolygonsController *polygonsController; -@property(nonatomic, strong) FGMPolylinesController *polylinesController; -@property(nonatomic, strong) FGMCirclesController *circlesController; - -// The controller that handles heatmaps -@property(nonatomic, strong) FGMHeatmapsController *heatmapsController; -@property(nonatomic, strong) FGMTileOverlaysController *tileOverlaysController; -@property(nonatomic, strong) FGMGroundOverlaysController *groundOverlaysController; -// The resulting error message, if any, from the last attempt to set the map style. -// This is used to provide access to errors after the fact, since the map style is generally set at -// creation time and there's no mechanism to return non-fatal error details during platform view -// initialization. -@property(nonatomic, copy) NSString *styleError; -// The main Pigeon API implementation, separate to avoid lifetime extension. -@property(nonatomic, strong) FGMMapCallHandler *callHandler; -// The inspector API implementation, separate to avoid lifetime extension. -@property(nonatomic, strong) FGMMapInspector *inspector; - -@end - -@implementation FGMGoogleMapController - -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *)registrar { - GMSCameraPosition *camera = - FGMGetCameraPositionForPigeonCameraPosition(creationParameters.initialCameraPosition); - - GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init]; - options.frame = frame; - options.camera = camera; - NSString *mapId = creationParameters.mapConfiguration.mapId; - if (mapId.length > 0) { - options.mapID = [GMSMapID mapIDWithIdentifier:mapId]; - } - - GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options]; - - return [self initWithMapView:mapView - viewIdentifier:viewId - creationParameters:creationParameters - assetProvider:[[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar] - binaryMessenger:registrar.messenger]; -} - -- (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - assetProvider:(NSObject *)assetProvider - binaryMessenger:(NSObject *)binaryMessenger { - if (self = [super init]) { - _mapView = mapView; - - _mapView.accessibilityElementsHidden = NO; - // TODO(cyanglaz): avoid sending message to self in the middle of the init method. - // https://github.com/flutter/flutter/issues/104121 - [self interpretMapConfiguration:creationParameters.mapConfiguration]; - NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; - _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:binaryMessenger - messageChannelSuffix:pigeonSuffix]; - _mapEventHandler = - [[FGMDefaultMapEventHandler alloc] initWithCallbackHandler:_dartCallbackHandler]; - FGMPlatformMarkerType markerType = creationParameters.mapConfiguration.markerType; - _mapView.delegate = self; - _mapView.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; - _clusterManagersController = - [[FGMClusterManagersController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _markersController = [[FGMMarkersController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler - clusterManagersController:_clusterManagersController - assetProvider:assetProvider - markerType:markerType]; - _polygonsController = [[FGMPolygonsController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _polylinesController = [[FGMPolylinesController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _circlesController = [[FGMCirclesController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _heatmapsController = [[FGMHeatmapsController alloc] initWithMapView:_mapView]; - _tileOverlaysController = [[FGMTileOverlaysController alloc] initWithMapView:_mapView - tileProvider:self]; - _groundOverlaysController = - [[FGMGroundOverlaysController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler - assetProvider:assetProvider]; - [_clusterManagersController addClusterManagers:creationParameters.initialClusterManagers]; - [_markersController addMarkers:creationParameters.initialMarkers]; - [_polygonsController addPolygons:creationParameters.initialPolygons]; - [_polylinesController addPolylines:creationParameters.initialPolylines]; - [_circlesController addCircles:creationParameters.initialCircles]; - [_heatmapsController addHeatmaps:creationParameters.initialHeatmaps]; - [_tileOverlaysController addTileOverlays:creationParameters.initialTileOverlays]; - [_groundOverlaysController addGroundOverlays:creationParameters.initialGroundOverlays]; - - // Invoke clustering after markers are added. - [_clusterManagersController invokeClusteringForEachClusterManager]; - - [_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil]; - - _callHandler = [[FGMMapCallHandler alloc] initWithMapController:self - messenger:binaryMessenger - pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsApiWithSuffix(binaryMessenger, _callHandler, pigeonSuffix); - _inspector = [[FGMMapInspector alloc] initWithMapController:self - messenger:binaryMessenger - pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, _inspector, pigeonSuffix); - } - return self; -} - -- (void)dealloc { - // Unregister the API implementations so that they can be released; the registration created an - // owning reference. - SetUpFGMMapsApiWithSuffix(_callHandler.messenger, nil, _callHandler.pigeonSuffix); - SetUpFGMMapsInspectorApiWithSuffix(_inspector.messenger, nil, _inspector.pigeonSuffix); -} - -- (UIView *)view { - return self.mapView; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - if (object == self.mapView && [keyPath isEqualToString:@"frame"]) { - CGRect bounds = self.mapView.bounds; - if (CGRectEqualToRect(bounds, CGRectZero)) { - // The workaround is to fix an issue that the camera location is not current when - // the size of the map is zero at initialization. - // So We only care about the size of the `self.mapView`, ignore the frame changes when the - // size is zero. - return; - } - // We only observe the frame for initial setup. - [self.mapView removeObserver:self forKeyPath:@"frame"]; - [self.mapView moveCamera:[GMSCameraUpdate setCamera:self.mapView.camera]]; - } else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -- (void)showAtOrigin:(CGPoint)origin { - CGRect frame = {origin, self.mapView.frame.size}; - self.mapView.frame = frame; - self.mapView.hidden = NO; -} - -- (void)hide { - self.mapView.hidden = YES; -} - -- (GMSCameraPosition *)cameraPosition { - if (self.trackCameraPosition) { - return self.mapView.camera; - } else { - return nil; - } -} - -- (void)setCamera:(GMSCameraPosition *)camera { - self.mapView.camera = camera; -} - -- (void)setCameraTargetBounds:(GMSCoordinateBounds *)bounds { - self.mapView.cameraTargetBounds = bounds; -} - -- (void)setCompassEnabled:(BOOL)enabled { - self.mapView.settings.compassButton = enabled; -} - -- (void)setIndoorEnabled:(BOOL)enabled { - self.mapView.indoorEnabled = enabled; -} - -- (void)setTrafficEnabled:(BOOL)enabled { - self.mapView.trafficEnabled = enabled; -} - -- (void)setBuildingsEnabled:(BOOL)enabled { - self.mapView.buildingsEnabled = enabled; -} - -- (void)setMapType:(GMSMapViewType)mapType { - self.mapView.mapType = mapType; -} - -- (void)setMinZoom:(float)minZoom maxZoom:(float)maxZoom { - [self.mapView setMinZoom:minZoom maxZoom:maxZoom]; -} - -- (void)setPaddingTop:(float)top left:(float)left bottom:(float)bottom right:(float)right { - self.mapView.padding = UIEdgeInsetsMake(top, left, bottom, right); -} - -- (void)setRotateGesturesEnabled:(BOOL)enabled { - self.mapView.settings.rotateGestures = enabled; -} - -- (void)setScrollGesturesEnabled:(BOOL)enabled { - self.mapView.settings.scrollGestures = enabled; -} - -- (void)setTiltGesturesEnabled:(BOOL)enabled { - self.mapView.settings.tiltGestures = enabled; -} - -- (void)setTrackCameraPosition:(BOOL)enabled { - _trackCameraPosition = enabled; -} - -- (void)setZoomGesturesEnabled:(BOOL)enabled { - self.mapView.settings.zoomGestures = enabled; -} - -- (void)setMyLocationEnabled:(BOOL)enabled { - self.mapView.myLocationEnabled = enabled; -} - -- (void)setMyLocationButtonEnabled:(BOOL)enabled { - self.mapView.settings.myLocationButton = enabled; -} - -/// Sets the map style, returing any error string as well as storing that error in `mapStyle` for -/// later access. -- (NSString *)setMapStyle:(NSString *)mapStyle { - NSString *errorString = nil; - if (mapStyle.length == 0) { - self.mapView.mapStyle = nil; - } else { - NSError *error; - GMSMapStyle *style = [GMSMapStyle styleWithJSONString:mapStyle error:&error]; - if (style) { - self.mapView.mapStyle = style; - } else { - errorString = [error localizedDescription]; - } - } - self.styleError = errorString; - return errorString; -} - -#pragma mark - GMSMapViewDelegate methods - -- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture { - [self.mapEventHandler didStartCameraMove]; -} - -- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position { - if (self.trackCameraPosition) { - [self.mapEventHandler didMoveCameraToPosition:FGMGetPigeonCameraPositionForPosition(position)]; - } -} - -- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position { - [self.mapEventHandler didIdleCamera]; -} - -- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { - if ([marker.userData isKindOfClass:[GMUStaticCluster class]]) { - GMUStaticCluster *cluster = marker.userData; - [self.clusterManagersController didTapCluster:cluster]; - // When NO is returned, the map will focus on the cluster. - return NO; - } - return - [self.markersController didTapMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker)]; -} - -- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker { - [self.markersController - didEndDraggingMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didBeginDraggingMarker:(GMSMarker *)marker { - [self.markersController - didStartDraggingMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker { - [self.markersController didDragMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker { - [self.markersController - didTapInfoWindowOfMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker)]; -} -- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay { - NSString *overlayId = overlay.userData[0]; - if ([self.polylinesController hasPolylineWithIdentifier:overlayId]) { - [self.polylinesController didTapPolylineWithIdentifier:overlayId]; - } else if ([self.polygonsController hasPolygonWithIdentifier:overlayId]) { - [self.polygonsController didTapPolygonWithIdentifier:overlayId]; - } else if ([self.circlesController hasCircleWithIdentifier:overlayId]) { - [self.circlesController didTapCircleWithIdentifier:overlayId]; - } else if ([self.groundOverlaysController hasGroundOverlaysWithIdentifier:overlayId]) { - [self.groundOverlaysController didTapGroundOverlayWithIdentifier:overlayId]; - } -} - -- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.mapEventHandler didTapAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; -} - -- (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.mapEventHandler didLongPressAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; -} - -- (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { - FGMPlatformCameraTargetBounds *cameraTargetBounds = config.cameraTargetBounds; - if (cameraTargetBounds) { - [self setCameraTargetBounds:cameraTargetBounds.bounds - ? FGMGetCoordinateBoundsForPigeonLatLngBounds( - cameraTargetBounds.bounds) - : nil]; - } - NSNumber *compassEnabled = config.compassEnabled; - if (compassEnabled != nil) { - [self setCompassEnabled:compassEnabled.boolValue]; - } - NSNumber *indoorEnabled = config.indoorViewEnabled; - if (indoorEnabled != nil) { - [self setIndoorEnabled:indoorEnabled.boolValue]; - } - NSNumber *trafficEnabled = config.trafficEnabled; - if (trafficEnabled != nil) { - [self setTrafficEnabled:trafficEnabled.boolValue]; - } - NSNumber *buildingsEnabled = config.buildingsEnabled; - if (buildingsEnabled != nil) { - [self setBuildingsEnabled:buildingsEnabled.boolValue]; - } - FGMPlatformMapTypeBox *mapType = config.mapType; - if (mapType) { - [self setMapType:FGMGetMapViewTypeForPigeonMapType(mapType.value)]; - } - FGMPlatformZoomRange *zoomData = config.minMaxZoomPreference; - if (zoomData) { - float minZoom = zoomData.min != nil ? zoomData.min.floatValue : kGMSMinZoomLevel; - float maxZoom = zoomData.max != nil ? zoomData.max.floatValue : kGMSMaxZoomLevel; - [self setMinZoom:minZoom maxZoom:maxZoom]; - } - FGMPlatformEdgeInsets *padding = config.padding; - if (padding) { - [self setPaddingTop:padding.top left:padding.left bottom:padding.bottom right:padding.right]; - } - - NSNumber *rotateGesturesEnabled = config.rotateGesturesEnabled; - if (rotateGesturesEnabled != nil) { - [self setRotateGesturesEnabled:rotateGesturesEnabled.boolValue]; - } - NSNumber *scrollGesturesEnabled = config.scrollGesturesEnabled; - if (scrollGesturesEnabled != nil) { - [self setScrollGesturesEnabled:scrollGesturesEnabled.boolValue]; - } - NSNumber *tiltGesturesEnabled = config.tiltGesturesEnabled; - if (tiltGesturesEnabled != nil) { - [self setTiltGesturesEnabled:tiltGesturesEnabled.boolValue]; - } - NSNumber *trackCameraPosition = config.trackCameraPosition; - if (trackCameraPosition != nil) { - [self setTrackCameraPosition:trackCameraPosition.boolValue]; - } - NSNumber *zoomGesturesEnabled = config.zoomGesturesEnabled; - if (zoomGesturesEnabled != nil) { - [self setZoomGesturesEnabled:zoomGesturesEnabled.boolValue]; - } - NSNumber *myLocationEnabled = config.myLocationEnabled; - if (myLocationEnabled != nil) { - [self setMyLocationEnabled:myLocationEnabled.boolValue]; - } - NSNumber *myLocationButtonEnabled = config.myLocationButtonEnabled; - if (myLocationButtonEnabled != nil) { - [self setMyLocationButtonEnabled:myLocationButtonEnabled.boolValue]; - } - NSString *style = config.style; - if (style) { - [self setMapStyle:style]; - } -} - -#pragma mark - FGMTileProviderDelegate - -- (void)tileWithOverlayIdentifier:(NSString *)tileOverlayId - location:(FGMPlatformPoint *)location - zoom:(NSInteger)zoom - completion:(void (^)(FGMPlatformTile *_Nullable, - FlutterError *_Nullable))completion { - [self.dartCallbackHandler tileWithOverlayIdentifier:tileOverlayId - location:location - zoom:zoom - completion:completion]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapCallHandler. -@implementation FGMMapCallHandler - -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix { - self = [super init]; - if (self) { - _controller = controller; - _messenger = messenger; - _pigeonSuffix = suffix; - _transactionWrapper = [[FGMCATransactionWrapper alloc] init]; - } - return self; -} - -- (void)waitForMapWithError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - // No-op; this call just ensures synchronization with the platform thread. -} - -- (void)updateCirclesByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.circlesController addCircles:toAdd]; - [self.controller.circlesController changeCircles:toChange]; - [self.controller.circlesController removeCirclesWithIdentifiers:idsToRemove]; -} - -- (void)updateHeatmapsByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.heatmapsController addHeatmaps:toAdd]; - [self.controller.heatmapsController changeHeatmaps:toChange]; - [self.controller.heatmapsController removeHeatmapsWithIdentifiers:idsToRemove]; -} - -- (void)updateWithMapConfiguration:(nonnull FGMPlatformMapConfiguration *)configuration - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller interpretMapConfiguration:configuration]; -} - -- (void)updateMarkersByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.markersController addMarkers:toAdd]; - [self.controller.markersController changeMarkers:toChange]; - [self.controller.markersController removeMarkersWithIdentifiers:idsToRemove]; - - // Invoke clustering after markers are added. - [self.controller.clusterManagersController invokeClusteringForEachClusterManager]; -} - -- (void)updateClusterManagersByAdding:(nonnull NSArray *)toAdd - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.clusterManagersController addClusterManagers:toAdd]; - [self.controller.clusterManagersController removeClusterManagersWithIdentifiers:idsToRemove]; -} - -- (void)updatePolygonsByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.polygonsController addPolygons:toAdd]; - [self.controller.polygonsController changePolygons:toChange]; - [self.controller.polygonsController removePolygonWithIdentifiers:idsToRemove]; -} - -- (void)updatePolylinesByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.polylinesController addPolylines:toAdd]; - [self.controller.polylinesController changePolylines:toChange]; - [self.controller.polylinesController removePolylineWithIdentifiers:idsToRemove]; -} - -- (void)updateTileOverlaysByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.tileOverlaysController addTileOverlays:toAdd]; - [self.controller.tileOverlaysController changeTileOverlays:toChange]; - [self.controller.tileOverlaysController removeTileOverlayWithIdentifiers:idsToRemove]; -} - -- (void)updateGroundOverlaysByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.groundOverlaysController addGroundOverlays:toAdd]; - [self.controller.groundOverlaysController changeGroundOverlays:toChange]; - [self.controller.groundOverlaysController removeGroundOverlaysWithIdentifiers:idsToRemove]; -} - -- (nullable FGMPlatformLatLng *) - latLngForScreenCoordinate:(nonnull FGMPlatformPoint *)screenCoordinate - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getLatLng called prior to map initialization" - details:nil]; - return nil; - } - CGPoint point = FGMGetCGPointForPigeonPoint(screenCoordinate); - CLLocationCoordinate2D latlng = [self.controller.mapView.projection coordinateForPoint:point]; - return FGMGetPigeonLatLngForCoordinate(latlng); -} - -- (nullable FGMPlatformPoint *) - screenCoordinatesForLatLng:(nonnull FGMPlatformLatLng *)latLng - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getScreenCoordinate called prior to map initialization" - details:nil]; - return nil; - } - CLLocationCoordinate2D location = FGMGetCoordinateForPigeonLatLng(latLng); - CGPoint point = [self.controller.mapView.projection pointForCoordinate:location]; - return FGMGetPigeonPointForCGPoint(point); -} - -- (nullable FGMPlatformLatLngBounds *)visibleMapRegion: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getVisibleRegion called prior to map initialization" - details:nil]; - return nil; - } - GMSVisibleRegion visibleRegion = self.controller.mapView.projection.visibleRegion; - GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:visibleRegion]; - return FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds); -} - -- (void)moveCameraWithUpdate:(nonnull FGMPlatformCameraUpdate *)cameraUpdate - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate); - if (!update) { - *error = [FlutterError errorWithCode:@"Invalid update" - message:@"Unrecognized camera update" - details:nil]; - return; - } - [self.controller.mapView moveCamera:update]; -} - -- (void)animateCameraWithUpdate:(nonnull FGMPlatformCameraUpdate *)cameraUpdate - duration:(nullable NSNumber *)durationMilliseconds - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate); - if (!update) { - *error = [FlutterError errorWithCode:@"Invalid update" - message:@"Unrecognized camera update" - details:nil]; - return; - } - FGMCATransactionWrapper *transaction = - durationMilliseconds != nil ? self.transactionWrapper : nil; - [transaction begin]; - [transaction setAnimationDuration:[durationMilliseconds doubleValue] / 1000]; - [self.controller.mapView animateWithCameraUpdate:update]; - [transaction commit]; -} - -- (nullable NSNumber *)currentZoomLevel:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.camera.zoom); -} - -- (void)showInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.markersController showMarkerInfoWindowWithIdentifier:markerId error:error]; -} - -- (void)hideInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.markersController hideMarkerInfoWindowWithIdentifier:markerId error:error]; -} - -- (nullable NSNumber *) - isShowingInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - return [self.controller.markersController isInfoWindowShownForMarkerWithIdentifier:markerId - error:error]; -} - -- (nullable NSString *)setStyle:(nonnull NSString *)style - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [self.controller setMapStyle:style]; -} - -- (nullable NSString *)lastStyleError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return self.controller.styleError; -} - -- (void)clearTileCacheForOverlayWithIdentifier:(nonnull NSString *)tileOverlayId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.tileOverlaysController clearTileCacheWithIdentifier:tileOverlayId]; -} - -- (nullable FlutterStandardTypedData *)takeSnapshotWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSMapView *mapView = self.controller.mapView; - if (!mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"takeSnapshot called prior to map initialization" - details:nil]; - return nil; - } - UIGraphicsImageRenderer *renderer = - [[UIGraphicsImageRenderer alloc] initWithSize:mapView.bounds.size]; - // For some unknown reason mapView.layer::renderInContext API returns a blank image on iOS 17. - // So we have to use drawViewHierarchyInRect API. - UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) { - [mapView drawViewHierarchyInRect:mapView.bounds afterScreenUpdates:YES]; - }]; - NSData *imageData = UIImagePNGRepresentation(image); - return imageData ? [FlutterStandardTypedData typedDataWithBytes:imageData] : nil; -} - -- (nullable NSNumber *)isAdvancedMarkersAvailable: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - NSUInteger advancedMarkerFlag = - self.controller.mapView.mapCapabilities & GMSMapCapabilityFlagsAdvancedMarkers; - return [NSNumber numberWithBool:(advancedMarkerFlag != 0)]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapInspector. -@implementation FGMMapInspector - -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix { - self = [super init]; - if (self) { - _controller = controller; - _messenger = messenger; - _pigeonSuffix = suffix; - } - return self; -} - -- (nullable NSNumber *)areBuildingsEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.buildingsEnabled); -} - -- (nullable NSNumber *)areRotateGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.rotateGestures); -} - -- (nullable NSNumber *)areScrollGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.scrollGestures); -} - -- (nullable NSNumber *)areTiltGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.tiltGestures); -} - -- (nullable NSNumber *)areZoomGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.zoomGestures); -} - -- (nullable FGMPlatformTileLayer *) - tileOverlayWithIdentifier:(nonnull NSString *)tileOverlayId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSTileLayer *layer = - [self.controller.tileOverlaysController tileOverlayWithIdentifier:tileOverlayId].layer; - if (!layer) { - return nil; - } - return [FGMPlatformTileLayer makeWithVisible:(layer.map != nil) - fadeIn:layer.fadeIn - opacity:layer.opacity - zIndex:layer.zIndex]; -} - -- (nullable FGMPlatformHeatmap *) - heatmapWithIdentifier:(nonnull NSString *)heatmapId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [self.controller.heatmapsController heatmapWithIdentifier:heatmapId]; -} - -- (nullable NSArray *) - clustersWithIdentifier:(NSString *)clusterManagerId - error:(FlutterError *_Nullable *_Nonnull)error { - return [self.controller.clusterManagersController clustersWithIdentifier:clusterManagerId - error:error]; -} - -- (nullable NSNumber *)isCompassEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.compassButton); -} - -- (nullable NSNumber *)isMyLocationButtonEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.myLocationButton); -} - -- (nullable NSNumber *)isTrafficEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.trafficEnabled); -} - -- (nullable FGMPlatformZoomRange *)zoomRange: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [FGMPlatformZoomRange makeWithMin:@(self.controller.mapView.minZoom) - max:@(self.controller.mapView.maxZoom)]; -} - -- (nullable FGMPlatformGroundOverlay *) - groundOverlayWithIdentifier:(NSString *)groundOverlayId - error:(FlutterError *_Nullable __autoreleasing *)error { - return [self.controller.groundOverlaysController groundOverlayWithIdentifier:groundOverlayId]; -} - -- (nullable FGMPlatformCameraPosition *)cameraPosition: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return FGMGetPigeonCameraPositionForPosition(self.controller.mapView.camera); -} - -@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGoogleMapsPlugin.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGoogleMapsPlugin.m deleted file mode 100644 index 072d675b17b8..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGoogleMapsPlugin.m +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FGMGoogleMapsPlugin.h" - -@import GoogleMaps; - -#pragma mark - GoogleMaps plugin implementation - -// Declares a GMSServices method that was added in SDK 9.2, so that it can be -// conditionally called. It is declared on NSObject to avoid duplicate -// declaration errors when compiling with newer SDKs. -// TODO(stuartmorgan): Remove this once all packages sharing this file require -// SDK 9.2 or later. See https://github.com/flutter/flutter/issues/187106 -@interface NSObject (MapsSDK92Extensions) -+ (void)addInternalUsageAttributionID:(nonnull NSString *)internalUsageAttributionID; -@end - -@implementation FGMGoogleMapsPlugin - -+ (void)registerWithRegistrar:(NSObject *)registrar { - FGMGoogleMapFactory *googleMapFactory = [[FGMGoogleMapFactory alloc] initWithRegistrar:registrar]; - [registrar registerViewFactory:googleMapFactory - withId:@"plugins.flutter.dev/google_maps_ios" - gestureRecognizersBlockingPolicy: - FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded]; - if ([GMSServices respondsToSelector:@selector(addInternalUsageAttributionID:)]) { - [GMSServices addInternalUsageAttributionID:@"gmp_flutter_googlemapsflutter_ios"]; - } -} - -@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapController.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapController.swift new file mode 100644 index 000000000000..b5b822b9442b --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapController.swift @@ -0,0 +1,938 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps +import GoogleMapsUtils + +#if canImport(google_maps_flutter_ios_sdk9_objc) + import google_maps_flutter_ios_sdk9_objc +#endif + +/// Non-test implementation of FGMAssetProvider, wrapping a Flutter plugin registrar. +class DefaultAssetProvider: NSObject, FGMAssetProvider { + weak var registrar: FlutterPluginRegistrar? + + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + super.init() + } + + func lookupKey(forAsset asset: String) -> String? { + return registrar?.lookupKey(forAsset: asset) + } + + func lookupKey(forAsset asset: String, fromPackage package: String) -> String? { + return registrar?.lookupKey(forAsset: asset, fromPackage: package) + } + + func imageNamed(_ name: String) -> UIImage? { + return UIImage(named: name) + } +} + +/// Non-test implementation of FGMMapEventDelegate, wrapping a FGMMapsCallbackApi instance. +class DefaultMapEventHandler: NSObject, FGMMapEventDelegate { + let callbackHandler: FGMMapsCallbackApi + + init(callbackHandler: FGMMapsCallbackApi) { + self.callbackHandler = callbackHandler + super.init() + } + + func didStartCameraMove() { + callbackHandler.didStartCameraMove { _ in } + } + + func didMoveCamera(to cameraPosition: FGMPlatformCameraPosition) { + callbackHandler.didMoveCamera(to: cameraPosition) { _ in } + } + + func didIdleCamera() { + callbackHandler.didIdleCamera { _ in } + } + + func didTap(atPosition position: FGMPlatformLatLng) { + callbackHandler.didTap(atPosition: position) { _ in } + } + + func didLongPress(atPosition position: FGMPlatformLatLng) { + callbackHandler.didLongPress(atPosition: position) { _ in } + } + + func didTapMarker(withIdentifier markerId: String) { + callbackHandler.didTapMarker(withIdentifier: markerId) { _ in } + } + + func didStartDragForMarker( + withIdentifier markerId: String, atPosition position: FGMPlatformLatLng + ) { + callbackHandler.didStartDragForMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didDragMarker(withIdentifier markerId: String, atPosition position: FGMPlatformLatLng) { + callbackHandler.didDragMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didEndDragForMarker(withIdentifier markerId: String, atPosition position: FGMPlatformLatLng) + { + callbackHandler.didEndDragForMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didTapInfoWindowOfMarker(withIdentifier markerId: String) { + callbackHandler.didTapInfoWindowOfMarker(withIdentifier: markerId) { _ in } + } + + func didTapCircle(withIdentifier circleId: String) { + callbackHandler.didTapCircle(withIdentifier: circleId) { _ in } + } + + func didTap(_ cluster: FGMPlatformCluster) { + callbackHandler.didTap(cluster) { _ in } + } + + func didTapPolygon(withIdentifier polygonId: String) { + callbackHandler.didTapPolygon(withIdentifier: polygonId) { _ in } + } + + func didTapPolyline(withIdentifier polylineId: String) { + callbackHandler.didTapPolyline(withIdentifier: polylineId) { _ in } + } + + func didTapGroundOverlay(withIdentifier groundOverlayId: String) { + callbackHandler.didTapGroundOverlay(withIdentifier: groundOverlayId) { _ in } + } +} + +public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformView { + /// The Google Maps SDK map view managed by this controller. + let mapView: GMSMapView + /// The Pigeon callback API implementation, used to send events to the Dart side. + let dartCallbackHandler: FGMMapsCallbackApi + /// The map SDK event handler, which routes events to the Dart callback handler. + let mapEventHandler: DefaultMapEventHandler + /// The main Pigeon API implementation, separate to avoid lifetime extension. + let callHandler: MapCallHandler + /// The inspector API implementation, separate to avoid lifetime extension. + let inspector: MapInspector + /// A shim to pass tile requests to `dartCallbackHandler`. This is a separate object to avoid init ordering issues. + private let tileProvider: ConcreteTileProvider + /// Whether to send notifications about camera position changes to Dart. + var trackCameraPosition = false + + /// Sub-controllers for managing individual map features. + let clusterManagersController: FGMClusterManagersController + let markersController: FGMMarkersController + let polygonsController: FGMPolygonsController + let polylinesController: FGMPolylinesController + let circlesController: FGMCirclesController + let heatmapsController: FGMHeatmapsController + let tileOverlaysController: FGMTileOverlaysController + let groundOverlaysController: FGMGroundOverlaysController + + // The resulting error message, if any, from the last attempt to set the map style. + // This is used to provide access to errors after the fact, since the map style is generally set at + // creation time and there's no mechanism to return non-fatal error details during platform view + // initialization. + var styleError: String? + /// Whether we are currently observing the "frame" key path on `mapView`. + private var isObservingFrame = false + + public convenience init( + frame: CGRect, + viewIdentifier viewId: Int64, + creationParameters: FGMPlatformMapViewCreationParams, + registrar: FlutterPluginRegistrar + ) { + let camera = FGMGetCameraPositionForPigeonCameraPosition( + creationParameters.initialCameraPosition) + + let options = GMSMapViewOptions() + options.frame = frame + options.camera = camera + if let mapId = creationParameters.mapConfiguration.mapId, !mapId.isEmpty { + options.mapID = GMSMapID(identifier: mapId) + } + + self.init( + mapView: GMSMapView(options: options), + viewIdentifier: viewId, + creationParameters: creationParameters, + assetProvider: DefaultAssetProvider(registrar: registrar), + binaryMessenger: registrar.messenger() + ) + } + + public init( + mapView: GMSMapView, + viewIdentifier viewId: Int64, + creationParameters: FGMPlatformMapViewCreationParams, + assetProvider: FGMAssetProvider, + binaryMessenger: FlutterBinaryMessenger + ) { + self.mapView = mapView + mapView.accessibilityElementsHidden = false + mapView.paddingAdjustmentBehavior = .never + // The code below must be kept in sync with `interpretMapConfiguration`. The small amount of + // duplication here is to avoid having to defer all map view configuration until after the + // sub-controllers are given the map view. + let (styleUpdateAttempted, errorString) = GoogleMapController.updateMapView( + mapView, fromConfiguration: creationParameters.mapConfiguration) + if styleUpdateAttempted { + styleError = errorString + } + if let trackCameraPosition = creationParameters.mapConfiguration.trackCameraPosition { + self.trackCameraPosition = trackCameraPosition.boolValue + } + // End duplicate code. + + let pigeonSuffix = String(format: "%lld", viewId) + dartCallbackHandler = FGMMapsCallbackApi( + binaryMessenger: binaryMessenger, + messageChannelSuffix: pigeonSuffix + ) + + mapEventHandler = DefaultMapEventHandler(callbackHandler: dartCallbackHandler) + + let markerType = creationParameters.mapConfiguration.markerType + + clusterManagersController = FGMClusterManagersController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + markersController = FGMMarkersController( + mapView: mapView, + eventDelegate: mapEventHandler, + clusterManagersController: clusterManagersController, + assetProvider: assetProvider, + markerType: markerType + ) + polygonsController = FGMPolygonsController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + polylinesController = FGMPolylinesController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + circlesController = FGMCirclesController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + heatmapsController = FGMHeatmapsController(mapView: mapView) + tileProvider = ConcreteTileProvider(dartCallbackHandler: dartCallbackHandler) + tileOverlaysController = FGMTileOverlaysController( + mapView: mapView, + tileProvider: tileProvider + ) + groundOverlaysController = FGMGroundOverlaysController( + mapView: mapView, + eventDelegate: mapEventHandler, + assetProvider: assetProvider + ) + + clusterManagersController.add(creationParameters.initialClusterManagers) + markersController.add(creationParameters.initialMarkers) + polygonsController.add(creationParameters.initialPolygons) + polylinesController.add(creationParameters.initialPolylines) + circlesController.add(creationParameters.initialCircles) + heatmapsController.add(creationParameters.initialHeatmaps) + tileOverlaysController.add(creationParameters.initialTileOverlays) + groundOverlaysController.add(creationParameters.initialGroundOverlays) + + callHandler = MapCallHandler( + messenger: binaryMessenger, + pigeonSuffix: pigeonSuffix + ) + inspector = MapInspector( + messenger: binaryMessenger, + pigeonSuffix: pigeonSuffix + ) + + super.init() + + callHandler.controller = self + SetUpFGMMapsApiWithSuffix(binaryMessenger, callHandler, pigeonSuffix) + inspector.controller = self + SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, inspector, pigeonSuffix) + + mapView.delegate = self + isObservingFrame = true + mapView.addObserver(self, forKeyPath: "frame", options: [], context: nil) + + // Invoke clustering after everything is configured. + clusterManagersController.invokeClusteringForEachClusterManager() + } + + deinit { + if isObservingFrame { + mapView.removeObserver(self, forKeyPath: "frame") + } + SetUpFGMMapsApiWithSuffix(callHandler.messenger, nil, callHandler.pigeonSuffix) + SetUpFGMMapsInspectorApiWithSuffix(inspector.messenger, nil, inspector.pigeonSuffix) + } + + public func view() -> UIView { + return mapView + } + + override public func observeValue( + forKeyPath keyPath: String?, + of object: Any?, + change: [NSKeyValueChangeKey: Any]?, + context: UnsafeMutableRawPointer? + ) { + if let keyPath = keyPath, + let gmsMapView = object as? GMSMapView, + gmsMapView == mapView, + keyPath == "frame" + { + let bounds = mapView.bounds + if bounds.equalTo(.zero) { + // The workaround is to fix an issue that the camera location is not current when + // the size of the map is zero at initialization. + // So We only care about the size of the `self.mapView`, ignore the frame changes when the + // size is zero. + return + } + // We only observe the frame for initial setup. + isObservingFrame = false + mapView.removeObserver(self, forKeyPath: "frame") + mapView.moveCamera(GMSCameraUpdate.setCamera(mapView.camera)) + } else { + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + } + } + + public func showAtOrigin(_ origin: CGPoint) { + mapView.frame = CGRect(origin: origin, size: mapView.frame.size) + mapView.isHidden = false + } + + public func hide() { + mapView.isHidden = true + } + + public func cameraPosition() -> GMSCameraPosition? { + return trackCameraPosition ? mapView.camera : nil + } + + func setCamera(_ camera: GMSCameraPosition) { + mapView.camera = camera + } + + /// Sets the map style, returning any error string as well as storing that error in `styleError` for + /// later access. + func setMapStyle(_ mapStyle: String) -> String? { + let (style, errorString) = GoogleMapController.parseMapStyle(mapStyle) + if errorString == nil { + mapView.mapStyle = style + } + styleError = errorString + return errorString + } + + /// Attempts to construct a GMSMapStyle from a JSON style string, returning the style, as well as + /// an error string if it the style could not be created. + /// + /// - If the String? value is non-nil, that description of the error should be stored in + /// `styleError` by the caller for later access, and the style should be set on the map. + /// - If the String? value is nil, the style should be set on the map. The style may be nil if + /// the input string is empty, which is how the platform channel expresses clearing the style. + static func parseMapStyle(_ jsonStyle: String) -> (GMSMapStyle?, String?) { + if jsonStyle.isEmpty { + return (nil, nil) + } + do { + let style = try GMSMapStyle(jsonString: jsonStyle) + return (style, nil) + } catch let error { + return (nil, error.localizedDescription) + } + } + + // MARK: - GMSMapViewDelegate methods + + public func mapView(_ mapView: GMSMapView, willMove gesture: Bool) { + mapEventHandler.didStartCameraMove() + } + + public func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { + if trackCameraPosition { + mapEventHandler.didMoveCamera(to: FGMGetPigeonCameraPositionForPosition(position)) + } + } + + public func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) { + mapEventHandler.didIdleCamera() + } + + public func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { + if let cluster = marker.userData as? GMUStaticCluster { + clusterManagersController.didTap(cluster) + return false + } + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + return markersController.didTapMarker(withIdentifier: markerId) + } + return false + } + + public func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didEndDraggingMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didStartDraggingMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didDragMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didTapInfoWindowOfMarker(withIdentifier: markerId) + } + } + + public func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) { + guard let userDataArray = overlay.userData as? [Any], + let overlayId = userDataArray.first as? String + else { + return + } + if polylinesController.hasPolyline(withIdentifier: overlayId) == true { + polylinesController.didTapPolyline(withIdentifier: overlayId) + } else if polygonsController.hasPolygon(withIdentifier: overlayId) == true { + polygonsController.didTapPolygon(withIdentifier: overlayId) + } else if circlesController.hasCircle(withIdentifier: overlayId) == true { + circlesController.didTapCircle(withIdentifier: overlayId) + } else if groundOverlaysController.hasGroundOverlays(withIdentifier: overlayId) == true { + groundOverlaysController.didTapGroundOverlay(withIdentifier: overlayId) + } + } + + public func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) { + mapEventHandler.didTap(atPosition: FGMGetPigeonLatLngForCoordinate(coordinate)) + } + + public func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) { + mapEventHandler.didLongPress(atPosition: FGMGetPigeonLatLngForCoordinate(coordinate)) + } + + func interpretMapConfiguration(_ config: FGMPlatformMapConfiguration) { + // Any changes here must also be made to the `init` method above. See the comment there for + // details. + let (styleUpdateAttempted, errorString) = GoogleMapController.updateMapView( + mapView, fromConfiguration: config) + if styleUpdateAttempted { + styleError = errorString + } + if let trackCameraPosition = config.trackCameraPosition { + self.trackCameraPosition = trackCameraPosition.boolValue + } + } + + /// Updates the given map view with new configuration options. + /// + /// Returns a boolean indicating whether a style update was attempted, and an error string + /// describing any error interpreting the style in `config`. If the boolean is true, the error + /// string should be stored in `styleError` for later access. + static func updateMapView( + _ mapView: GMSMapView, fromConfiguration config: FGMPlatformMapConfiguration + ) -> (Bool, String?) { + if let cameraTargetBounds = config.cameraTargetBounds { + if let bounds = cameraTargetBounds.bounds { + mapView.cameraTargetBounds = FGMGetCoordinateBoundsForPigeonLatLngBounds(bounds) + } else { + mapView.cameraTargetBounds = nil + } + } + if let compassEnabled = config.compassEnabled { + mapView.settings.compassButton = compassEnabled.boolValue + } + if let indoorEnabled = config.indoorViewEnabled { + mapView.isIndoorEnabled = indoorEnabled.boolValue + } + if let trafficEnabled = config.trafficEnabled { + mapView.isTrafficEnabled = trafficEnabled.boolValue + } + if let buildingsEnabled = config.buildingsEnabled { + mapView.isBuildingsEnabled = buildingsEnabled.boolValue + } + if let mapType = config.mapType { + mapView.mapType = FGMGetMapViewTypeForPigeonMapType(mapType.value) + } + if let zoomData = config.minMaxZoomPreference { + let minZoom = zoomData.min?.floatValue ?? kGMSMinZoomLevel + let maxZoom = zoomData.max?.floatValue ?? kGMSMaxZoomLevel + mapView.setMinZoom(minZoom, maxZoom: maxZoom) + } + if let padding = config.padding { + mapView.padding = UIEdgeInsets( + top: CGFloat(padding.top), + left: CGFloat(padding.left), + bottom: CGFloat(padding.bottom), + right: CGFloat(padding.right) + ) + } + if let rotateGesturesEnabled = config.rotateGesturesEnabled { + mapView.settings.rotateGestures = rotateGesturesEnabled.boolValue + } + if let scrollGesturesEnabled = config.scrollGesturesEnabled { + mapView.settings.scrollGestures = scrollGesturesEnabled.boolValue + } + if let tiltGesturesEnabled = config.tiltGesturesEnabled { + mapView.settings.tiltGestures = tiltGesturesEnabled.boolValue + } + if let zoomGesturesEnabled = config.zoomGesturesEnabled { + mapView.settings.zoomGestures = zoomGesturesEnabled.boolValue + } + if let myLocationEnabled = config.myLocationEnabled { + mapView.isMyLocationEnabled = myLocationEnabled.boolValue + } + if let myLocationButtonEnabled = config.myLocationButtonEnabled { + mapView.settings.myLocationButton = myLocationButtonEnabled.boolValue + } + if let mapStyle = config.style { + let (style, errorString) = GoogleMapController.parseMapStyle(mapStyle) + if errorString == nil { + mapView.mapStyle = style + } + return (true, errorString) + } + return (false, nil) + } +} + +// TODO(stuartmorgan): Remove this in favor of an extension to add FGMTileProviderDelegate to +// the Pigeon Flutter API object once this plugin has switched to Swift Pigeon generation +// (adjusting the protocol to match the Swift version of the signature). +private class ConcreteTileProvider: NSObject, FGMTileProviderDelegate { + let handler: FGMMapsCallbackApi + + init(dartCallbackHandler: FGMMapsCallbackApi) { + handler = dartCallbackHandler + } + + public func tile( + withOverlayIdentifier tileOverlayId: String, + location: FGMPlatformPoint, + zoom: Int, + completion: @escaping (FGMPlatformTile?, FlutterError?) -> Void + ) { + handler.tile( + withOverlayIdentifier: tileOverlayId, + location: location, + zoom: zoom, + completion: completion + ) + } +} + +class MapCallHandler: NSObject, FGMMapsApi { + weak var controller: GoogleMapController? + let messenger: FlutterBinaryMessenger + let pigeonSuffix: String + var transactionWrapper: FGMCATransactionProtocol + + init( + messenger: FlutterBinaryMessenger, + pigeonSuffix suffix: String + ) { + self.messenger = messenger + self.pigeonSuffix = suffix + self.transactionWrapper = FGMCATransactionWrapper() + super.init() + } + + func waitForMapWithError(_ error: AutoreleasingUnsafeMutablePointer) { + // No-op; this call just ensures synchronization with the platform thread. + } + + func updateCircles( + byAdding toAdd: [FGMPlatformCircle], changing toChange: [FGMPlatformCircle], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.circlesController.add(toAdd) + controller?.circlesController.change(toChange) + controller?.circlesController.removeCircles(withIdentifiers: idsToRemove) + } + + func updateHeatmaps( + byAdding toAdd: [FGMPlatformHeatmap], changing toChange: [FGMPlatformHeatmap], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.heatmapsController.add(toAdd) + controller?.heatmapsController.change(toChange) + controller?.heatmapsController.removeHeatmaps(withIdentifiers: idsToRemove) + } + + func update( + with configuration: FGMPlatformMapConfiguration, + error: AutoreleasingUnsafeMutablePointer + ) { + controller?.interpretMapConfiguration(configuration) + } + + func updateMarkers( + byAdding toAdd: [FGMPlatformMarker], changing toChange: [FGMPlatformMarker], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.add(toAdd) + controller?.markersController.change(toChange) + controller?.markersController.removeMarkers(withIdentifiers: idsToRemove) + controller?.clusterManagersController.invokeClusteringForEachClusterManager() + } + + func updateClusterManagers( + byAdding toAdd: [FGMPlatformClusterManager], removing idsToRemove: [String], + error: AutoreleasingUnsafeMutablePointer + ) { + controller?.clusterManagersController.add(toAdd) + controller?.clusterManagersController.removeClusterManagers(withIdentifiers: idsToRemove) + } + + func updatePolygons( + byAdding toAdd: [FGMPlatformPolygon], changing toChange: [FGMPlatformPolygon], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.polygonsController.add(toAdd) + controller?.polygonsController.change(toChange) + controller?.polygonsController.removePolygon(withIdentifiers: idsToRemove) + } + + func updatePolylines( + byAdding toAdd: [FGMPlatformPolyline], changing toChange: [FGMPlatformPolyline], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.polylinesController.add(toAdd) + controller?.polylinesController.change(toChange) + controller?.polylinesController.removePolyline(withIdentifiers: idsToRemove) + } + + func updateTileOverlays( + byAdding toAdd: [FGMPlatformTileOverlay], changing toChange: [FGMPlatformTileOverlay], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.tileOverlaysController.add(toAdd) + controller?.tileOverlaysController.change(toChange) + controller?.tileOverlaysController.removeTileOverlay(withIdentifiers: idsToRemove) + } + + func updateGroundOverlays( + byAdding toAdd: [FGMPlatformGroundOverlay], changing toChange: [FGMPlatformGroundOverlay], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.groundOverlaysController.add(toAdd) + controller?.groundOverlaysController.change(toChange) + controller?.groundOverlaysController.removeGroundOverlays(withIdentifiers: idsToRemove) + } + + func latLng( + forScreenCoordinate screenCoordinate: FGMPlatformPoint, + error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformLatLng? { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getLatLng called prior to map initialization", + details: nil + ) + return nil + } + let point = FGMGetCGPointForPigeonPoint(screenCoordinate) + let latlng = mapView.projection.coordinate(for: point) + return FGMGetPigeonLatLngForCoordinate(latlng) + } + + func screenCoordinates( + for latLng: FGMPlatformLatLng, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformPoint? { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getScreenCoordinate called prior to map initialization", + details: nil + ) + return nil + } + let location = FGMGetCoordinateForPigeonLatLng(latLng) + let point = mapView.projection.point(for: location) + return FGMGetPigeonPointForCGPoint(point) + } + + func visibleMapRegion(_ error: AutoreleasingUnsafeMutablePointer) + -> FGMPlatformLatLngBounds? + { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getVisibleRegion called prior to map initialization", + details: nil + ) + return nil + } + let visibleRegion = mapView.projection.visibleRegion() + let bounds = GMSCoordinateBounds(region: visibleRegion) + return FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds) + } + + func moveCamera( + with cameraUpdate: FGMPlatformCameraUpdate, + error: AutoreleasingUnsafeMutablePointer + ) { + guard let update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate) else { + error.pointee = FlutterError( + code: "Invalid update", + message: "Unrecognized camera update", + details: nil + ) + return + } + controller?.mapView.moveCamera(update) + } + + func animateCamera( + with cameraUpdate: FGMPlatformCameraUpdate, duration durationMilliseconds: NSNumber?, + error: AutoreleasingUnsafeMutablePointer + ) { + guard let update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate) else { + error.pointee = FlutterError( + code: "Invalid update", + message: "Unrecognized camera update", + details: nil + ) + return + } + let transaction = durationMilliseconds != nil ? transactionWrapper : nil + transaction?.begin() + if let duration = durationMilliseconds { + transaction?.setAnimationDuration(duration.doubleValue / 1000.0) + } + controller?.mapView.animate(with: update) + transaction?.commit() + } + + func currentZoomLevel(_ error: AutoreleasingUnsafeMutablePointer) -> NSNumber? { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.camera.zoom) + } + + func showInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.showMarkerInfoWindow(withIdentifier: markerId, error: error) + } + + func hideInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.hideMarkerInfoWindow(withIdentifier: markerId, error: error) + } + + func isShowingInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) -> NSNumber? { + return controller?.markersController.isInfoWindowShownForMarker( + withIdentifier: markerId, error: error) + } + + func setStyle(_ style: String, error: AutoreleasingUnsafeMutablePointer) -> String? + { + return controller?.setMapStyle(style) + } + + func lastStyleError(_ error: AutoreleasingUnsafeMutablePointer) -> String? { + return controller?.styleError + } + + func clearTileCacheForOverlay( + withIdentifier tileOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.tileOverlaysController.clearTileCache(withIdentifier: tileOverlayId) + } + + func takeSnapshotWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> FlutterStandardTypedData? + { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "takeSnapshot called prior to map initialization", + details: nil + ) + return nil + } + let renderer = UIGraphicsImageRenderer(size: mapView.bounds.size) + let image = renderer.image { context in + mapView.drawHierarchy(in: mapView.bounds, afterScreenUpdates: true) + } + if let imageData = image.pngData() { + return FlutterStandardTypedData(bytes: imageData) + } + return nil + } + + func isAdvancedMarkersAvailable(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return false + } + return NSNumber(value: mapView.mapCapabilities.contains(.advancedMarkers)) + } +} + +class MapInspector: NSObject, FGMMapsInspectorApi { + weak var controller: GoogleMapController? + let messenger: FlutterBinaryMessenger + let pigeonSuffix: String + + init( + messenger: FlutterBinaryMessenger, + pigeonSuffix suffix: String + ) { + self.messenger = messenger + self.pigeonSuffix = suffix + super.init() + } + + func areBuildingsEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.isBuildingsEnabled) + } + + func areRotateGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.rotateGestures) + } + + func areScrollGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.scrollGestures) + } + + func areTiltGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.tiltGestures) + } + + func areZoomGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.zoomGestures) + } + + func tileOverlay( + withIdentifier tileOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformTileLayer? { + guard let controller = controller, + let layer = controller.tileOverlaysController.tileOverlay(withIdentifier: tileOverlayId)? + .layer + else { + return nil + } + return FGMPlatformTileLayer.make( + withVisible: layer.map != nil, + fadeIn: layer.fadeIn, + opacity: Double(layer.opacity), + zIndex: Int(layer.zIndex) + ) + } + + func heatmap( + withIdentifier heatmapId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformHeatmap? { + return controller?.heatmapsController.heatmap(withIdentifier: heatmapId) + } + + func clusters( + withIdentifier clusterManagerId: String, error: AutoreleasingUnsafeMutablePointer + ) -> [FGMPlatformCluster]? { + return controller?.clusterManagersController.clusters( + withIdentifier: clusterManagerId, error: error) + } + + func isCompassEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.compassButton) + } + + func isMyLocationButtonEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.myLocationButton) + } + + func isTrafficEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.isTrafficEnabled) + } + + func zoomRange(_ error: AutoreleasingUnsafeMutablePointer) -> FGMPlatformZoomRange? + { + guard let mapView = controller?.mapView else { + return nil + } + return FGMPlatformZoomRange.make( + withMin: NSNumber(value: mapView.minZoom), + max: NSNumber(value: mapView.maxZoom) + ) + } + + func groundOverlay( + withIdentifier groundOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformGroundOverlay? { + return controller?.groundOverlaysController.groundOverlay(withIdentifier: groundOverlayId) + } + + func cameraPosition(_ error: AutoreleasingUnsafeMutablePointer) + -> FGMPlatformCameraPosition? + { + guard let mapView = controller?.mapView else { + return nil + } + return FGMGetPigeonCameraPositionForPosition(mapView.camera) + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapFactory.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapFactory.swift new file mode 100644 index 000000000000..bbd27c27ee46 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapFactory.swift @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps + +#if canImport(google_maps_flutter_ios_sdk9_objc) + import google_maps_flutter_ios_sdk9_objc +#endif + +class GoogleMapFactory: NSObject, FlutterPlatformViewFactory { + weak var registrar: FlutterPluginRegistrar? + static var sharedMapServices = GMSServices.sharedServices() + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + } + + func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) + -> any FlutterPlatformView + { + // Precache shared map services, if needed. Initializing this prepares GMSServices + // on a background thread controlled by the GoogleMaps framework. + _ = GoogleMapFactory.sharedMapServices + + return GoogleMapController( + frame: frame, viewIdentifier: viewId, + creationParameters: args as! FGMPlatformMapViewCreationParams, registrar: registrar!) + } + + func createArgsCodec() -> any FlutterMessageCodec & NSObjectProtocol { + return FGMGetGoogleMapsFlutterPigeonMessagesCodec() + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapsPlugin.swift b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapsPlugin.swift new file mode 100644 index 000000000000..8ca573ad6d9f --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/GoogleMapsPlugin.swift @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps + +public class GoogleMapsPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let factory = GoogleMapFactory(registrar: registrar) + registrar.register( + factory, + withId: "plugins.flutter.dev/google_maps_ios", + gestureRecognizersBlockingPolicy: + FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded) + GMSServices.addInternalUsageAttributionID("gmp_flutter_googlemapsflutter_ios") + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapController.h deleted file mode 100644 index b723c8d3658e..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapController.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMCATransactionWrapper.h" -#import "FGMCircleController.h" -#import "FGMClusterManagersController.h" -#import "FGMMarkerController.h" -#import "FGMPolygonController.h" -#import "FGMPolylineController.h" -#import "google_maps_flutter_pigeon_messages.g.h" - -NS_ASSUME_NONNULL_BEGIN - -// Defines map overlay controllable from Flutter. -@interface FGMGoogleMapController : NSObject -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *)registrar; -- (void)showAtOrigin:(CGPoint)origin; -- (void)hide; -- (nullable GMSCameraPosition *)cameraPosition; -@end - -// Allows the engine to create new Google Map instances. -@interface FGMGoogleMapFactory : NSObject -- (instancetype)initWithRegistrar:(NSObject *)registrar; -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapController_Test.h deleted file mode 100644 index 5e1fa9371b2c..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapController_Test.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMAssetProvider.h" -#import "FGMCATransactionWrapper.h" -#import "FGMGoogleMapController.h" - -NS_ASSUME_NONNULL_BEGIN - -/// Implementation of the Pigeon maps API. -/// -/// This is a separate object from the maps controller because the Pigeon API registration keeps a -/// strong reference to the implementor, but as the FlutterPlatformView, the lifetime of the -/// FGMGoogleMapController instance is what needs to trigger Pigeon unregistration, so can't be -/// the target of the registration. -@interface FGMMapCallHandler : NSObject - -/// The transaction wrapper to use for camera animations. -@property(nonatomic, strong) id transactionWrapper; - -@end - -/// Implementation of the Pigeon maps inspector API. -/// -/// This is a separate object from the maps controller because the Pigeon API registration keeps a -/// strong reference to the implementor, but as the FlutterPlatformView, the lifetime of the -/// FGMGoogleMapController instance is what needs to trigger Pigeon unregistration, so can't be -/// the target of the registration. -@interface FGMMapInspector : NSObject - -/// Initializes a Pigeon API for inpector with a map controller. -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix; - -@end - -@interface FGMGoogleMapController (Test) - -/// Initializes a map controller with a concrete map view. -/// -/// @param mapView A map view that will be displayed by the controller -/// @param viewId A unique identifier for the controller. -/// @param creationParameters Parameters for initialising the map view. -/// @param assetProvider The asset provider to use for looking up assets. -/// @param binaryMessenger The binary messenger to use for sending messages to Dart. -- (instancetype)initWithMapView:(GMSMapView *)mapView - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - assetProvider:(NSObject *)assetProvider - binaryMessenger:(NSObject *)binaryMessenger; - -// The main Pigeon API implementation. -@property(nonatomic, strong, readonly) FGMMapCallHandler *callHandler; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapsPlugin.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapsPlugin.h deleted file mode 100644 index ec294eb3d3e9..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGoogleMapsPlugin.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMCircleController.h" -#import "FGMClusterManagersController.h" -#import "FGMGoogleMapController.h" -#import "FGMMarkerController.h" -#import "FGMPolygonController.h" -#import "FGMPolylineController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FGMGoogleMapsPlugin : NSObject -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMCATransactionWrapper.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMCATransactionWrapper.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMCATransactionWrapper.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMCATransactionWrapper.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMCircleController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMCircleController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMCircleController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMCircleController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMClusterManagersController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMClusterManagersController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMClusterManagersController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMClusterManagersController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMConversionUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMConversionUtils.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMConversionUtils.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMConversionUtils.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGroundOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMGroundOverlayController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMGroundOverlayController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMGroundOverlayController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMHeatmapController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMHeatmapController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMHeatmapController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMHeatmapController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMImageUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMImageUtils.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMImageUtils.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMImageUtils.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMMarkerController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMMarkerController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMMarkerController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMMarkerController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMMarkerUserData.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMMarkerUserData.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMMarkerUserData.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMMarkerUserData.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMPolygonController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMPolygonController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMPolygonController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMPolygonController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMPolylineController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMPolylineController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMPolylineController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMTileOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMTileOverlayController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/FGMTileOverlayController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/FGMTileOverlayController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/google_maps_flutter_pigeon_messages.g.m b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/google_maps_flutter_pigeon_messages.g.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/google_maps_flutter_pigeon_messages.g.m rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/google_maps_flutter_pigeon_messages.g.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMAssetProvider.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMAssetProvider.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMAssetProvider.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMAssetProvider.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMCATransactionWrapper.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMCATransactionWrapper.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMCATransactionWrapper.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMCATransactionWrapper.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMCircleController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMCircleController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMCircleController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMCircleController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMCircleController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMCircleController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMCircleController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMCircleController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMClusterManagersController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMClusterManagersController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMClusterManagersController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMClusterManagersController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMConversionUtils.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMConversionUtils.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMConversionUtils.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMConversionUtils.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGroundOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMGroundOverlayController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGroundOverlayController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMGroundOverlayController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGroundOverlayController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMGroundOverlayController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMGroundOverlayController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMGroundOverlayController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMHeatmapController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMHeatmapController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMHeatmapController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMHeatmapController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMHeatmapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMHeatmapController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMHeatmapController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMHeatmapController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMImageUtils.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMImageUtils.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMImageUtils.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMImageUtils.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMapEventDelegate.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMapEventDelegate.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMapEventDelegate.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMapEventDelegate.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMarkerController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMarkerController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMarkerController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMarkerController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMarkerController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMarkerController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMarkerController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMarkerController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMarkerUserData.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMarkerUserData.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMMarkerUserData.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMMarkerUserData.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolygonController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolygonController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolygonController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolygonController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolygonController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolygonController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolygonController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolygonController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolylineController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolylineController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolylineController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolylineController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolylineController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMPolylineController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMPolylineController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMTileOverlayController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMTileOverlayController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMTileOverlayController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMTileOverlayController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMTileOverlayController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/FGMTileOverlayController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/FGMTileOverlayController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/GoogleMapsUtilsTrampoline.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/GoogleMapsUtilsTrampoline.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/GoogleMapsUtilsTrampoline.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/GoogleMapsUtilsTrampoline.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/google_maps_flutter_pigeon_messages.g.h b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/google_maps_flutter_pigeon_messages.g.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/google_maps_flutter_pigeon_messages.g.h rename to packages/google_maps_flutter/google_maps_flutter_ios_sdk9/ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/google_maps_flutter_pigeon_messages.g.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/pubspec.yaml index cbfc993524f7..c363234471b8 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/pubspec.yaml +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/pubspec.yaml @@ -2,7 +2,7 @@ name: google_maps_flutter_ios_sdk9 description: iOS implementation of the google_maps_flutter plugin using Google Maps SDK 9. repository: https://github.com/flutter/packages/tree/main/packages/google_maps_flutter/google_maps_flutter_ios_sdk9 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+maps%22 -version: 2.18.6 +version: 2.18.7 environment: sdk: ^3.10.0 @@ -13,7 +13,7 @@ flutter: implements: google_maps_flutter platforms: ios: - pluginClass: FGMGoogleMapsPlugin + pluginClass: GoogleMapsPlugin dartPluginClass: GoogleMapsFlutterIOS dependencies: diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/sync_shared_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/sync_shared_files.dart index 8711068a5604..5fc97464adb5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/sync_shared_files.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/sync_shared_files.dart @@ -33,7 +33,7 @@ void _syncSharedFiles(Directory packageRoot, String packageName, Directory share .map((e) => p.basename(e.path)) .where( (name) => - name.startsWith('google_maps_flutter_ios') && + name.startsWith('google_maps_flutter_ios_') && name != _sharedSourceRootName && name != packageName, ) @@ -116,8 +116,9 @@ void _syncFile(File source, String destinationPath, String destinationPackageNam ].any((pattern) => source.absolute.path.contains(pattern))) { updatePackageNameInPathReferences(File(destinationPath), destinationPackageName); } - // Native unit tests need to import the Swift package. - if (source.absolute.path.contains('/RunnerTests/')) { + // Native unit tests need to import the Swift package, and the Swift files need to import the + // Obj-C sub-package until the Swift migration is complete. + if (source.absolute.path.contains('/RunnerTests/') || source.absolute.path.endsWith('.swift')) { updatePackageNameInImports(File(destinationPath), destinationPackageName); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/unshared_source_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/unshared_source_files.dart index 7e0205065261..2b9405a62502 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/unshared_source_files.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/unshared_source_files.dart @@ -13,5 +13,5 @@ const intentionallyUnsharedSourceFiles = [ // Each package will have its own list. 'tool/unshared_source_files.dart', // Unshared due to https://github.com/flutter/flutter/issues/183441. - 'ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9/include/google_maps_flutter_ios_sdk9/GoogleMapsUtilsTrampoline.h', + 'ios/google_maps_flutter_ios_sdk9/Sources/google_maps_flutter_ios_sdk9_objc/include/google_maps_flutter_ios_sdk9_objc/GoogleMapsUtilsTrampoline.h', ]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/utils.dart b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/utils.dart index 3fb80a0b7e64..2508a25c786a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/utils.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_sdk9/tool/utils.dart @@ -49,9 +49,9 @@ List unexpectedUnsharedSourceFiles( /// Adjusts a package-relative path to account for the package name being part of /// the directory structure for Swift packages. String sharedSourceRelativePathForPackagePath(String packageRelativePath) { - return packageRelativePath.replaceAll( - RegExp(r'/google_maps_flutter_ios[_\w\d]*/'), - '/google_maps_flutter_ios/', + return packageRelativePath.replaceAllMapped( + RegExp(r'/google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?)/'), + (match) => '/google_maps_flutter_ios${match.group(1)}/', ); } @@ -61,7 +61,10 @@ String packageRelativePathForSharedSourceRelativePath( String packageName, String sharedSourceRelativePath, ) { - return sharedSourceRelativePath.replaceAll('/google_maps_flutter_ios/', '/$packageName/'); + return sharedSourceRelativePath.replaceAllMapped( + RegExp(r'/google_maps_flutter_ios((?:_objc)?)/'), + (match) => '/$packageName${match.group(1)}/', + ); } /// Returns the contents of the file with any differences caused only by the @@ -70,7 +73,8 @@ String normalizedFileContents(File file) { return file .readAsStringSync() // Ignore differences caused only by the package name. - .replaceAll(RegExp(r'google_maps_flutter_ios_[\w\d]+'), 'google_maps_flutter_ios') + .replaceAll(RegExp(r'google_maps_flutter_ios_sdk[\d]+'), 'google_maps_flutter_ios') + .replaceAll(RegExp(r'google_maps_flutter_ios_sdk[\d]+_objc'), 'google_maps_flutter_ios_objc') // Package name diffs could change line wrapping, so collapse whitespace. .replaceAll(RegExp(r'[\s\n]+'), ' ') .trim(); @@ -84,7 +88,7 @@ String normalizedFileContents(File file) { /// should be replaced in all files. void updatePackageNameInPathReferences(File file, String packageName) { final String newContents = file.readAsStringSync().replaceAllMapped( - RegExp(r'google_maps_flutter_ios[_\w\d]*([:/])'), + RegExp(r'google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?[:/])'), (match) => '$packageName${match.group(1)}', ); file.writeAsStringSync(newContents); @@ -100,13 +104,16 @@ void updatePackageNameInImports(File file, String packageName) { .readAsStringSync() // Package imports. .replaceAllMapped( - RegExp(r'^(@?(?:testable )?)import google_maps_flutter_ios[_\w\d]*(;?)$', multiLine: true), + RegExp( + r'^(@?(?:testable )?)import google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?;?)$', + multiLine: true, + ), (match) => '${match.group(1)}import $packageName${match.group(2)}', ) // Bridging header. .replaceAllMapped( - RegExp(r'^#import '#import <$packageName/', + RegExp(r'^#import '#import <$packageName${match.group(1)}/', ); file.writeAsStringSync(newContents); } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/README.md b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/README.md index c40737087d93..1d159b89f25b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/README.md +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/README.md @@ -6,6 +6,11 @@ has its own copy of these files—allowing us to maintain multiple major version wrappers without complex branching—each implementation package has a CI test that validates that its copies of these files have not diverged. +Note: `google_maps_flutter_ios` is **not** part of the shared source system. +It is frozen, with ongoing development happening only in the `_sdk*` versions, +since `google_maps_flutter_ios` cannot adopt Swift without breaking the +dynamic CocoaPods resolution system. + This means that for almost all changes to `google_maps_flutter_ios_*`, the changes need to be copied here, and to all instances of the package, with any instance of the package name itself changed in each copy. After making changes diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/GoogleMapsTests.swift b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/GoogleMapsTests.swift index bcf512afe221..2a6480ded87b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/GoogleMapsTests.swift +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/GoogleMapsTests.swift @@ -60,7 +60,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { @Test func plugin() { // Verify that creating an actual plugin instance succeeds. - let _ = FGMGoogleMapsPlugin() + let _ = GoogleMapsPlugin() } @Test func frameObserver() { @@ -69,7 +69,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { options.frame = frame options.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0) let mapView = PartiallyMockedMapView(options: options) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -86,20 +86,6 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { #expect(mapView.frameObserverCount == 0) } - @Test func mapsServiceSync() { - // The API requires a registrar, but this test doesn't actually use it, so just pass in a - // dummy object rather than set up a full mock. - let registrar = StubPluginRegistrar() - let factory1 = FGMGoogleMapFactory(registrar: registrar) - #expect(factory1.sharedMapServices != nil) - let factory2 = FGMGoogleMapFactory(registrar: registrar) - // Test pointer equality, should be same retained singleton +[GMSServices sharedServices] object. - // Retaining the opaque object should be enough to avoid multiple internal initializations, - // but don't test the internals of the GoogleMaps API. Assume that it does what is documented. - // https://developers.google.com/maps/documentation/ios-sdk/reference/interface_g_m_s_services#a436e03c32b1c0be74e072310a7158831 - #expect(factory1.sharedMapServices as AnyObject === factory2.sharedMapServices as AnyObject) - } - @Test func handleResultTileDownsamplesWideGamutImages() throws { let controller = FGMTileProviderController() @@ -128,7 +114,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -160,7 +146,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -200,7 +186,7 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { let mapView = PartiallyMockedMapView(options: mapViewOptions) let binaryMessenger = StubBinaryMessenger() - let controller = FGMGoogleMapController( + let controller = GoogleMapController( mapView: mapView, viewIdentifier: 0, creationParameters: emptyCreationParameters(), @@ -208,11 +194,8 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { binaryMessenger: binaryMessenger ) - let inspector = FGMMapInspector( - mapController: controller, - messenger: binaryMessenger, - pigeonSuffix: "0" - ) + let inspector = MapInspector(messenger: binaryMessenger, pigeonSuffix: "0") + inspector.controller = controller var error: FlutterError? = nil let cameraPosition = try #require(inspector.cameraPosition(&error)) @@ -263,4 +246,67 @@ class StubPluginRegistrar: NSObject, FlutterPluginRegistrar { initialGroundOverlays: [] ) } + + @Test func frameObserverRemovedOnDeinitIfNeverFired() { + let options = GMSMapViewOptions() + options.frame = .zero + options.camera = GMSCameraPosition(latitude: 0, longitude: 0, zoom: 0) + let mapView = PartiallyMockedMapView(options: options) + + var controller: GoogleMapController? = GoogleMapController( + mapView: mapView, + viewIdentifier: 0, + creationParameters: emptyCreationParameters(), + assetProvider: TestAssetProvider(), + binaryMessenger: StubBinaryMessenger() + ) + + #expect(mapView.frameObserverCount == 1) + + // Deallocate the controller + controller = nil + + #expect(mapView.frameObserverCount == 0) + } + + @Test func styleErrorPersistsAcrossConfigUpdates() { + let mapView = PartiallyMockedMapView(options: GMSMapViewOptions()) + let controller = GoogleMapController( + mapView: mapView, + viewIdentifier: 0, + creationParameters: emptyCreationParameters(), + assetProvider: TestAssetProvider(), + binaryMessenger: StubBinaryMessenger() + ) + + // Set an invalid style to trigger an error + _ = controller.setMapStyle("invalid json") + #expect(controller.styleError != nil) + + // Update config without style + let config = FGMPlatformMapConfiguration.make( + withCompassEnabled: true, + cameraTargetBounds: nil, + mapType: nil, + minMaxZoomPreference: nil, + rotateGesturesEnabled: nil, + scrollGesturesEnabled: nil, + tiltGesturesEnabled: nil, + trackCameraPosition: nil, + zoomGesturesEnabled: nil, + myLocationEnabled: nil, + myLocationButtonEnabled: nil, + padding: nil, + indoorViewEnabled: nil, + trafficEnabled: nil, + buildingsEnabled: nil, + markerType: .marker, + mapId: nil, + style: nil + ) + controller.interpretMapConfiguration(config) + + // The style error should still be present + #expect(controller.styleError != nil) + } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/RunnerTests-Bridging-Header.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/RunnerTests-Bridging-Header.h index 5382cd6501d2..65f248a36d49 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/RunnerTests-Bridging-Header.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/example/ios/RunnerTests/RunnerTests-Bridging-Header.h @@ -3,18 +3,13 @@ // found in the LICENSE file. // Import private _Test.h headers from the plugin framework -#import -#import -#import -#import -#import -#import -#import -#import - -@interface FGMGoogleMapFactory (Test) -@property(strong, nonatomic, readonly) id sharedMapServices; -@end +#import +#import +#import +#import +#import +#import +#import @interface FGMTileProviderController (Testing) - (UIImage *)handleResultTile:(nullable UIImage *)tileImage; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGoogleMapController.m deleted file mode 100644 index 5f609c9b00de..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGoogleMapController.m +++ /dev/null @@ -1,997 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import GoogleMapsUtils; - -#import "FGMGoogleMapController.h" -#import "FGMGoogleMapController_Test.h" - -#import "FGMAssetProvider.h" -#import "FGMConversionUtils.h" -#import "FGMGroundOverlayController.h" -#import "FGMHeatmapController.h" -#import "FGMMarkerUserData.h" -#import "FGMTileOverlayController.h" -#import "google_maps_flutter_pigeon_messages.g.h" - -@interface FGMGoogleMapFactory () - -@property(weak, nonatomic) NSObject *registrar; -@property(strong, nonatomic, readonly) id sharedMapServices; - -@end - -@implementation FGMGoogleMapFactory - -@synthesize sharedMapServices = _sharedMapServices; - -- (instancetype)initWithRegistrar:(NSObject *)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSObject *)createArgsCodec { - return FGMGetGoogleMapsFlutterPigeonMessagesCodec(); -} - -- (NSObject *)createWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - arguments:(id _Nullable)args { - // Precache shared map services, if needed. - // Retain the shared map services singleton, don't use the result for anything. - (void)[self sharedMapServices]; - - return [[FGMGoogleMapController alloc] initWithFrame:frame - viewIdentifier:viewId - creationParameters:args - registrar:self.registrar]; -} - -- (id)sharedMapServices { - if (_sharedMapServices == nil) { - // Calling this prepares GMSServices on a background thread controlled - // by the GoogleMaps framework. - // Retain the singleton to cache the initialization work across all map views. - _sharedMapServices = [GMSServices sharedServices]; - } - return _sharedMapServices; -} - -@end - -#pragma mark - - -/// Non-test implementation of FGMAssetProvider, wrapping a Flutter plugin -/// registrar. -@interface FGMDefaultAssetProvider : NSObject -@property(weak, nonatomic) NSObject *registrar; - -- (instancetype)initWithRegistrar:(NSObject *)registrar; -@end - -@implementation FGMDefaultAssetProvider - -- (instancetype)initWithRegistrar:(NSObject *)registrar { - self = [super init]; - if (self) { - _registrar = registrar; - } - return self; -} - -- (NSString *)lookupKeyForAsset:(NSString *)asset { - return [self.registrar lookupKeyForAsset:asset]; -} - -- (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package { - return [self.registrar lookupKeyForAsset:asset fromPackage:package]; -} - -- (UIImage *)imageNamed:(NSString *)name { - return [UIImage imageNamed:name]; -} - -@end - -#pragma mark - - -/// Non-test implementation of FGMAssetProvider, wrapping a FGMMapsCallbackApi -/// instance. -@interface FGMDefaultMapEventHandler : NSObject -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; - -- (instancetype)initWithCallbackHandler:(FGMMapsCallbackApi *)callbackHandler; -@end - -@implementation FGMDefaultMapEventHandler - -- (instancetype)initWithCallbackHandler:(FGMMapsCallbackApi *)callbackHandler { - self = [super init]; - if (self) { - _callbackHandler = callbackHandler; - } - return self; -} - -- (void)didStartCameraMove { - [self.callbackHandler didStartCameraMoveWithCompletion:^(FlutterError *_){ - }]; -} - -- (void)didMoveCameraToPosition:(FGMPlatformCameraPosition *)cameraPosition { - [self.callbackHandler didMoveCameraToPosition:cameraPosition - completion:^(FlutterError *_){ - }]; -} - -- (void)didIdleCamera { - [self.callbackHandler didIdleCameraWithCompletion:^(FlutterError *_){ - }]; -} - -- (void)didTapAtPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didTapAtPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didLongPressAtPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didLongPressAtPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapMarkerWithIdentifier:(NSString *)markerId { - [self.callbackHandler didTapMarkerWithIdentifier:markerId - completion:^(FlutterError *_){ - }]; -} - -- (void)didStartDragForMarkerWithIdentifier:(NSString *)markerId - atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didStartDragForMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didDragMarkerWithIdentifier:(NSString *)markerId atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didDragMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didEndDragForMarkerWithIdentifier:(NSString *)markerId - atPosition:(FGMPlatformLatLng *)position { - [self.callbackHandler didEndDragForMarkerWithIdentifier:markerId - atPosition:position - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapInfoWindowOfMarkerWithIdentifier:(NSString *)markerId { - [self.callbackHandler didTapInfoWindowOfMarkerWithIdentifier:markerId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapCircleWithIdentifier:(NSString *)circleId { - [self.callbackHandler didTapCircleWithIdentifier:circleId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapCluster:(FGMPlatformCluster *)cluster { - [self.callbackHandler didTapCluster:cluster - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapPolygonWithIdentifier:(NSString *)polygonId { - [self.callbackHandler didTapPolygonWithIdentifier:polygonId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapPolylineWithIdentifier:(NSString *)polylineId { - [self.callbackHandler didTapPolylineWithIdentifier:polylineId - completion:^(FlutterError *_){ - }]; -} - -- (void)didTapGroundOverlayWithIdentifier:(NSString *)groundOverlayId { - [self.callbackHandler didTapGroundOverlayWithIdentifier:groundOverlayId - completion:^(FlutterError *_){ - }]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapCallHandler. -@interface FGMMapCallHandler () -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix; - -/// The map controller this inspector corresponds to. -@property(nonatomic, weak) FGMGoogleMapController *controller; -/// The messenger this instance was registered with by Pigeon. -@property(nonatomic, copy) NSObject *messenger; -/// The suffix this instance was registered under with Pigeon. -@property(nonatomic, copy) NSString *pigeonSuffix; -@end - -#pragma mark - - -/// Private declarations of the FGMMapInspector. -@interface FGMMapInspector () - -/// The map controller this inspector corresponds to. -@property(nonatomic, weak) FGMGoogleMapController *controller; -/// The messenger this instance was registered with by Pigeon. -@property(nonatomic, copy) NSObject *messenger; -/// The suffix this instance was registered under with Pigeon. -@property(nonatomic, copy) NSString *pigeonSuffix; -@end - -#pragma mark - - -@interface FGMGoogleMapController () - -@property(nonatomic, strong) GMSMapView *mapView; -@property(nonatomic, strong) FGMMapsCallbackApi *dartCallbackHandler; -@property(nonatomic, strong) FGMDefaultMapEventHandler *mapEventHandler; -@property(nonatomic, assign) BOOL trackCameraPosition; -@property(nonatomic, strong) FGMClusterManagersController *clusterManagersController; -@property(nonatomic, strong) FGMMarkersController *markersController; -@property(nonatomic, strong) FGMPolygonsController *polygonsController; -@property(nonatomic, strong) FGMPolylinesController *polylinesController; -@property(nonatomic, strong) FGMCirclesController *circlesController; - -// The controller that handles heatmaps -@property(nonatomic, strong) FGMHeatmapsController *heatmapsController; -@property(nonatomic, strong) FGMTileOverlaysController *tileOverlaysController; -@property(nonatomic, strong) FGMGroundOverlaysController *groundOverlaysController; -// The resulting error message, if any, from the last attempt to set the map style. -// This is used to provide access to errors after the fact, since the map style is generally set at -// creation time and there's no mechanism to return non-fatal error details during platform view -// initialization. -@property(nonatomic, copy) NSString *styleError; -// The main Pigeon API implementation, separate to avoid lifetime extension. -@property(nonatomic, strong) FGMMapCallHandler *callHandler; -// The inspector API implementation, separate to avoid lifetime extension. -@property(nonatomic, strong) FGMMapInspector *inspector; - -@end - -@implementation FGMGoogleMapController - -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *)registrar { - GMSCameraPosition *camera = - FGMGetCameraPositionForPigeonCameraPosition(creationParameters.initialCameraPosition); - - GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init]; - options.frame = frame; - options.camera = camera; - NSString *mapId = creationParameters.mapConfiguration.mapId; - if (mapId.length > 0) { - options.mapID = [GMSMapID mapIDWithIdentifier:mapId]; - } - - GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options]; - - return [self initWithMapView:mapView - viewIdentifier:viewId - creationParameters:creationParameters - assetProvider:[[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar] - binaryMessenger:registrar.messenger]; -} - -- (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - assetProvider:(NSObject *)assetProvider - binaryMessenger:(NSObject *)binaryMessenger { - if (self = [super init]) { - _mapView = mapView; - - _mapView.accessibilityElementsHidden = NO; - // TODO(cyanglaz): avoid sending message to self in the middle of the init method. - // https://github.com/flutter/flutter/issues/104121 - [self interpretMapConfiguration:creationParameters.mapConfiguration]; - NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; - _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:binaryMessenger - messageChannelSuffix:pigeonSuffix]; - _mapEventHandler = - [[FGMDefaultMapEventHandler alloc] initWithCallbackHandler:_dartCallbackHandler]; - FGMPlatformMarkerType markerType = creationParameters.mapConfiguration.markerType; - _mapView.delegate = self; - _mapView.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; - _clusterManagersController = - [[FGMClusterManagersController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _markersController = [[FGMMarkersController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler - clusterManagersController:_clusterManagersController - assetProvider:assetProvider - markerType:markerType]; - _polygonsController = [[FGMPolygonsController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _polylinesController = [[FGMPolylinesController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _circlesController = [[FGMCirclesController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler]; - _heatmapsController = [[FGMHeatmapsController alloc] initWithMapView:_mapView]; - _tileOverlaysController = [[FGMTileOverlaysController alloc] initWithMapView:_mapView - tileProvider:self]; - _groundOverlaysController = - [[FGMGroundOverlaysController alloc] initWithMapView:_mapView - eventDelegate:_mapEventHandler - assetProvider:assetProvider]; - [_clusterManagersController addClusterManagers:creationParameters.initialClusterManagers]; - [_markersController addMarkers:creationParameters.initialMarkers]; - [_polygonsController addPolygons:creationParameters.initialPolygons]; - [_polylinesController addPolylines:creationParameters.initialPolylines]; - [_circlesController addCircles:creationParameters.initialCircles]; - [_heatmapsController addHeatmaps:creationParameters.initialHeatmaps]; - [_tileOverlaysController addTileOverlays:creationParameters.initialTileOverlays]; - [_groundOverlaysController addGroundOverlays:creationParameters.initialGroundOverlays]; - - // Invoke clustering after markers are added. - [_clusterManagersController invokeClusteringForEachClusterManager]; - - [_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil]; - - _callHandler = [[FGMMapCallHandler alloc] initWithMapController:self - messenger:binaryMessenger - pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsApiWithSuffix(binaryMessenger, _callHandler, pigeonSuffix); - _inspector = [[FGMMapInspector alloc] initWithMapController:self - messenger:binaryMessenger - pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, _inspector, pigeonSuffix); - } - return self; -} - -- (void)dealloc { - // Unregister the API implementations so that they can be released; the registration created an - // owning reference. - SetUpFGMMapsApiWithSuffix(_callHandler.messenger, nil, _callHandler.pigeonSuffix); - SetUpFGMMapsInspectorApiWithSuffix(_inspector.messenger, nil, _inspector.pigeonSuffix); -} - -- (UIView *)view { - return self.mapView; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context { - if (object == self.mapView && [keyPath isEqualToString:@"frame"]) { - CGRect bounds = self.mapView.bounds; - if (CGRectEqualToRect(bounds, CGRectZero)) { - // The workaround is to fix an issue that the camera location is not current when - // the size of the map is zero at initialization. - // So We only care about the size of the `self.mapView`, ignore the frame changes when the - // size is zero. - return; - } - // We only observe the frame for initial setup. - [self.mapView removeObserver:self forKeyPath:@"frame"]; - [self.mapView moveCamera:[GMSCameraUpdate setCamera:self.mapView.camera]]; - } else { - [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; - } -} - -- (void)showAtOrigin:(CGPoint)origin { - CGRect frame = {origin, self.mapView.frame.size}; - self.mapView.frame = frame; - self.mapView.hidden = NO; -} - -- (void)hide { - self.mapView.hidden = YES; -} - -- (GMSCameraPosition *)cameraPosition { - if (self.trackCameraPosition) { - return self.mapView.camera; - } else { - return nil; - } -} - -- (void)setCamera:(GMSCameraPosition *)camera { - self.mapView.camera = camera; -} - -- (void)setCameraTargetBounds:(GMSCoordinateBounds *)bounds { - self.mapView.cameraTargetBounds = bounds; -} - -- (void)setCompassEnabled:(BOOL)enabled { - self.mapView.settings.compassButton = enabled; -} - -- (void)setIndoorEnabled:(BOOL)enabled { - self.mapView.indoorEnabled = enabled; -} - -- (void)setTrafficEnabled:(BOOL)enabled { - self.mapView.trafficEnabled = enabled; -} - -- (void)setBuildingsEnabled:(BOOL)enabled { - self.mapView.buildingsEnabled = enabled; -} - -- (void)setMapType:(GMSMapViewType)mapType { - self.mapView.mapType = mapType; -} - -- (void)setMinZoom:(float)minZoom maxZoom:(float)maxZoom { - [self.mapView setMinZoom:minZoom maxZoom:maxZoom]; -} - -- (void)setPaddingTop:(float)top left:(float)left bottom:(float)bottom right:(float)right { - self.mapView.padding = UIEdgeInsetsMake(top, left, bottom, right); -} - -- (void)setRotateGesturesEnabled:(BOOL)enabled { - self.mapView.settings.rotateGestures = enabled; -} - -- (void)setScrollGesturesEnabled:(BOOL)enabled { - self.mapView.settings.scrollGestures = enabled; -} - -- (void)setTiltGesturesEnabled:(BOOL)enabled { - self.mapView.settings.tiltGestures = enabled; -} - -- (void)setTrackCameraPosition:(BOOL)enabled { - _trackCameraPosition = enabled; -} - -- (void)setZoomGesturesEnabled:(BOOL)enabled { - self.mapView.settings.zoomGestures = enabled; -} - -- (void)setMyLocationEnabled:(BOOL)enabled { - self.mapView.myLocationEnabled = enabled; -} - -- (void)setMyLocationButtonEnabled:(BOOL)enabled { - self.mapView.settings.myLocationButton = enabled; -} - -/// Sets the map style, returing any error string as well as storing that error in `mapStyle` for -/// later access. -- (NSString *)setMapStyle:(NSString *)mapStyle { - NSString *errorString = nil; - if (mapStyle.length == 0) { - self.mapView.mapStyle = nil; - } else { - NSError *error; - GMSMapStyle *style = [GMSMapStyle styleWithJSONString:mapStyle error:&error]; - if (style) { - self.mapView.mapStyle = style; - } else { - errorString = [error localizedDescription]; - } - } - self.styleError = errorString; - return errorString; -} - -#pragma mark - GMSMapViewDelegate methods - -- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture { - [self.mapEventHandler didStartCameraMove]; -} - -- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position { - if (self.trackCameraPosition) { - [self.mapEventHandler didMoveCameraToPosition:FGMGetPigeonCameraPositionForPosition(position)]; - } -} - -- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position { - [self.mapEventHandler didIdleCamera]; -} - -- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { - if ([marker.userData isKindOfClass:[GMUStaticCluster class]]) { - GMUStaticCluster *cluster = marker.userData; - [self.clusterManagersController didTapCluster:cluster]; - // When NO is returned, the map will focus on the cluster. - return NO; - } - return - [self.markersController didTapMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker)]; -} - -- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker { - [self.markersController - didEndDraggingMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didBeginDraggingMarker:(GMSMarker *)marker { - [self.markersController - didStartDraggingMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker { - [self.markersController didDragMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker) - location:marker.position]; -} - -- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker { - [self.markersController - didTapInfoWindowOfMarkerWithIdentifier:FGMGetMarkerIdentifierFromMarker(marker)]; -} -- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay { - NSString *overlayId = overlay.userData[0]; - if ([self.polylinesController hasPolylineWithIdentifier:overlayId]) { - [self.polylinesController didTapPolylineWithIdentifier:overlayId]; - } else if ([self.polygonsController hasPolygonWithIdentifier:overlayId]) { - [self.polygonsController didTapPolygonWithIdentifier:overlayId]; - } else if ([self.circlesController hasCircleWithIdentifier:overlayId]) { - [self.circlesController didTapCircleWithIdentifier:overlayId]; - } else if ([self.groundOverlaysController hasGroundOverlaysWithIdentifier:overlayId]) { - [self.groundOverlaysController didTapGroundOverlayWithIdentifier:overlayId]; - } -} - -- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.mapEventHandler didTapAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; -} - -- (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.mapEventHandler didLongPressAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; -} - -- (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { - FGMPlatformCameraTargetBounds *cameraTargetBounds = config.cameraTargetBounds; - if (cameraTargetBounds) { - [self setCameraTargetBounds:cameraTargetBounds.bounds - ? FGMGetCoordinateBoundsForPigeonLatLngBounds( - cameraTargetBounds.bounds) - : nil]; - } - NSNumber *compassEnabled = config.compassEnabled; - if (compassEnabled != nil) { - [self setCompassEnabled:compassEnabled.boolValue]; - } - NSNumber *indoorEnabled = config.indoorViewEnabled; - if (indoorEnabled != nil) { - [self setIndoorEnabled:indoorEnabled.boolValue]; - } - NSNumber *trafficEnabled = config.trafficEnabled; - if (trafficEnabled != nil) { - [self setTrafficEnabled:trafficEnabled.boolValue]; - } - NSNumber *buildingsEnabled = config.buildingsEnabled; - if (buildingsEnabled != nil) { - [self setBuildingsEnabled:buildingsEnabled.boolValue]; - } - FGMPlatformMapTypeBox *mapType = config.mapType; - if (mapType) { - [self setMapType:FGMGetMapViewTypeForPigeonMapType(mapType.value)]; - } - FGMPlatformZoomRange *zoomData = config.minMaxZoomPreference; - if (zoomData) { - float minZoom = zoomData.min != nil ? zoomData.min.floatValue : kGMSMinZoomLevel; - float maxZoom = zoomData.max != nil ? zoomData.max.floatValue : kGMSMaxZoomLevel; - [self setMinZoom:minZoom maxZoom:maxZoom]; - } - FGMPlatformEdgeInsets *padding = config.padding; - if (padding) { - [self setPaddingTop:padding.top left:padding.left bottom:padding.bottom right:padding.right]; - } - - NSNumber *rotateGesturesEnabled = config.rotateGesturesEnabled; - if (rotateGesturesEnabled != nil) { - [self setRotateGesturesEnabled:rotateGesturesEnabled.boolValue]; - } - NSNumber *scrollGesturesEnabled = config.scrollGesturesEnabled; - if (scrollGesturesEnabled != nil) { - [self setScrollGesturesEnabled:scrollGesturesEnabled.boolValue]; - } - NSNumber *tiltGesturesEnabled = config.tiltGesturesEnabled; - if (tiltGesturesEnabled != nil) { - [self setTiltGesturesEnabled:tiltGesturesEnabled.boolValue]; - } - NSNumber *trackCameraPosition = config.trackCameraPosition; - if (trackCameraPosition != nil) { - [self setTrackCameraPosition:trackCameraPosition.boolValue]; - } - NSNumber *zoomGesturesEnabled = config.zoomGesturesEnabled; - if (zoomGesturesEnabled != nil) { - [self setZoomGesturesEnabled:zoomGesturesEnabled.boolValue]; - } - NSNumber *myLocationEnabled = config.myLocationEnabled; - if (myLocationEnabled != nil) { - [self setMyLocationEnabled:myLocationEnabled.boolValue]; - } - NSNumber *myLocationButtonEnabled = config.myLocationButtonEnabled; - if (myLocationButtonEnabled != nil) { - [self setMyLocationButtonEnabled:myLocationButtonEnabled.boolValue]; - } - NSString *style = config.style; - if (style) { - [self setMapStyle:style]; - } -} - -#pragma mark - FGMTileProviderDelegate - -- (void)tileWithOverlayIdentifier:(NSString *)tileOverlayId - location:(FGMPlatformPoint *)location - zoom:(NSInteger)zoom - completion:(void (^)(FGMPlatformTile *_Nullable, - FlutterError *_Nullable))completion { - [self.dartCallbackHandler tileWithOverlayIdentifier:tileOverlayId - location:location - zoom:zoom - completion:completion]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapCallHandler. -@implementation FGMMapCallHandler - -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix { - self = [super init]; - if (self) { - _controller = controller; - _messenger = messenger; - _pigeonSuffix = suffix; - _transactionWrapper = [[FGMCATransactionWrapper alloc] init]; - } - return self; -} - -- (void)waitForMapWithError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - // No-op; this call just ensures synchronization with the platform thread. -} - -- (void)updateCirclesByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.circlesController addCircles:toAdd]; - [self.controller.circlesController changeCircles:toChange]; - [self.controller.circlesController removeCirclesWithIdentifiers:idsToRemove]; -} - -- (void)updateHeatmapsByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.heatmapsController addHeatmaps:toAdd]; - [self.controller.heatmapsController changeHeatmaps:toChange]; - [self.controller.heatmapsController removeHeatmapsWithIdentifiers:idsToRemove]; -} - -- (void)updateWithMapConfiguration:(nonnull FGMPlatformMapConfiguration *)configuration - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller interpretMapConfiguration:configuration]; -} - -- (void)updateMarkersByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.markersController addMarkers:toAdd]; - [self.controller.markersController changeMarkers:toChange]; - [self.controller.markersController removeMarkersWithIdentifiers:idsToRemove]; - - // Invoke clustering after markers are added. - [self.controller.clusterManagersController invokeClusteringForEachClusterManager]; -} - -- (void)updateClusterManagersByAdding:(nonnull NSArray *)toAdd - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.clusterManagersController addClusterManagers:toAdd]; - [self.controller.clusterManagersController removeClusterManagersWithIdentifiers:idsToRemove]; -} - -- (void)updatePolygonsByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.polygonsController addPolygons:toAdd]; - [self.controller.polygonsController changePolygons:toChange]; - [self.controller.polygonsController removePolygonWithIdentifiers:idsToRemove]; -} - -- (void)updatePolylinesByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.polylinesController addPolylines:toAdd]; - [self.controller.polylinesController changePolylines:toChange]; - [self.controller.polylinesController removePolylineWithIdentifiers:idsToRemove]; -} - -- (void)updateTileOverlaysByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.tileOverlaysController addTileOverlays:toAdd]; - [self.controller.tileOverlaysController changeTileOverlays:toChange]; - [self.controller.tileOverlaysController removeTileOverlayWithIdentifiers:idsToRemove]; -} - -- (void)updateGroundOverlaysByAdding:(nonnull NSArray *)toAdd - changing:(nonnull NSArray *)toChange - removing:(nonnull NSArray *)idsToRemove - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - [self.controller.groundOverlaysController addGroundOverlays:toAdd]; - [self.controller.groundOverlaysController changeGroundOverlays:toChange]; - [self.controller.groundOverlaysController removeGroundOverlaysWithIdentifiers:idsToRemove]; -} - -- (nullable FGMPlatformLatLng *) - latLngForScreenCoordinate:(nonnull FGMPlatformPoint *)screenCoordinate - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getLatLng called prior to map initialization" - details:nil]; - return nil; - } - CGPoint point = FGMGetCGPointForPigeonPoint(screenCoordinate); - CLLocationCoordinate2D latlng = [self.controller.mapView.projection coordinateForPoint:point]; - return FGMGetPigeonLatLngForCoordinate(latlng); -} - -- (nullable FGMPlatformPoint *) - screenCoordinatesForLatLng:(nonnull FGMPlatformLatLng *)latLng - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getScreenCoordinate called prior to map initialization" - details:nil]; - return nil; - } - CLLocationCoordinate2D location = FGMGetCoordinateForPigeonLatLng(latLng); - CGPoint point = [self.controller.mapView.projection pointForCoordinate:location]; - return FGMGetPigeonPointForCGPoint(point); -} - -- (nullable FGMPlatformLatLngBounds *)visibleMapRegion: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - if (!self.controller.mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"getVisibleRegion called prior to map initialization" - details:nil]; - return nil; - } - GMSVisibleRegion visibleRegion = self.controller.mapView.projection.visibleRegion; - GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:visibleRegion]; - return FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds); -} - -- (void)moveCameraWithUpdate:(nonnull FGMPlatformCameraUpdate *)cameraUpdate - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate); - if (!update) { - *error = [FlutterError errorWithCode:@"Invalid update" - message:@"Unrecognized camera update" - details:nil]; - return; - } - [self.controller.mapView moveCamera:update]; -} - -- (void)animateCameraWithUpdate:(nonnull FGMPlatformCameraUpdate *)cameraUpdate - duration:(nullable NSNumber *)durationMilliseconds - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate); - if (!update) { - *error = [FlutterError errorWithCode:@"Invalid update" - message:@"Unrecognized camera update" - details:nil]; - return; - } - FGMCATransactionWrapper *transaction = - durationMilliseconds != nil ? self.transactionWrapper : nil; - [transaction begin]; - [transaction setAnimationDuration:[durationMilliseconds doubleValue] / 1000]; - [self.controller.mapView animateWithCameraUpdate:update]; - [transaction commit]; -} - -- (nullable NSNumber *)currentZoomLevel:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.camera.zoom); -} - -- (void)showInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.markersController showMarkerInfoWindowWithIdentifier:markerId error:error]; -} - -- (void)hideInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.markersController hideMarkerInfoWindowWithIdentifier:markerId error:error]; -} - -- (nullable NSNumber *) - isShowingInfoWindowForMarkerWithIdentifier:(nonnull NSString *)markerId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - return [self.controller.markersController isInfoWindowShownForMarkerWithIdentifier:markerId - error:error]; -} - -- (nullable NSString *)setStyle:(nonnull NSString *)style - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [self.controller setMapStyle:style]; -} - -- (nullable NSString *)lastStyleError:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return self.controller.styleError; -} - -- (void)clearTileCacheForOverlayWithIdentifier:(nonnull NSString *)tileOverlayId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull) - error { - [self.controller.tileOverlaysController clearTileCacheWithIdentifier:tileOverlayId]; -} - -- (nullable FlutterStandardTypedData *)takeSnapshotWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSMapView *mapView = self.controller.mapView; - if (!mapView) { - *error = [FlutterError errorWithCode:@"GoogleMap uninitialized" - message:@"takeSnapshot called prior to map initialization" - details:nil]; - return nil; - } - UIGraphicsImageRenderer *renderer = - [[UIGraphicsImageRenderer alloc] initWithSize:mapView.bounds.size]; - // For some unknown reason mapView.layer::renderInContext API returns a blank image on iOS 17. - // So we have to use drawViewHierarchyInRect API. - UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) { - [mapView drawViewHierarchyInRect:mapView.bounds afterScreenUpdates:YES]; - }]; - NSData *imageData = UIImagePNGRepresentation(image); - return imageData ? [FlutterStandardTypedData typedDataWithBytes:imageData] : nil; -} - -- (nullable NSNumber *)isAdvancedMarkersAvailable: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - NSUInteger advancedMarkerFlag = - self.controller.mapView.mapCapabilities & GMSMapCapabilityFlagsAdvancedMarkers; - return [NSNumber numberWithBool:(advancedMarkerFlag != 0)]; -} - -@end - -#pragma mark - - -/// Private declarations of the FGMMapInspector. -@implementation FGMMapInspector - -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix { - self = [super init]; - if (self) { - _controller = controller; - _messenger = messenger; - _pigeonSuffix = suffix; - } - return self; -} - -- (nullable NSNumber *)areBuildingsEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.buildingsEnabled); -} - -- (nullable NSNumber *)areRotateGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.rotateGestures); -} - -- (nullable NSNumber *)areScrollGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.scrollGestures); -} - -- (nullable NSNumber *)areTiltGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.tiltGestures); -} - -- (nullable NSNumber *)areZoomGesturesEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.zoomGestures); -} - -- (nullable FGMPlatformTileLayer *) - tileOverlayWithIdentifier:(nonnull NSString *)tileOverlayId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - GMSTileLayer *layer = - [self.controller.tileOverlaysController tileOverlayWithIdentifier:tileOverlayId].layer; - if (!layer) { - return nil; - } - return [FGMPlatformTileLayer makeWithVisible:(layer.map != nil) - fadeIn:layer.fadeIn - opacity:layer.opacity - zIndex:layer.zIndex]; -} - -- (nullable FGMPlatformHeatmap *) - heatmapWithIdentifier:(nonnull NSString *)heatmapId - error:(FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [self.controller.heatmapsController heatmapWithIdentifier:heatmapId]; -} - -- (nullable NSArray *) - clustersWithIdentifier:(NSString *)clusterManagerId - error:(FlutterError *_Nullable *_Nonnull)error { - return [self.controller.clusterManagersController clustersWithIdentifier:clusterManagerId - error:error]; -} - -- (nullable NSNumber *)isCompassEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.compassButton); -} - -- (nullable NSNumber *)isMyLocationButtonEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.settings.myLocationButton); -} - -- (nullable NSNumber *)isTrafficEnabledWithError: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return @(self.controller.mapView.trafficEnabled); -} - -- (nullable FGMPlatformZoomRange *)zoomRange: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return [FGMPlatformZoomRange makeWithMin:@(self.controller.mapView.minZoom) - max:@(self.controller.mapView.maxZoom)]; -} - -- (nullable FGMPlatformGroundOverlay *) - groundOverlayWithIdentifier:(NSString *)groundOverlayId - error:(FlutterError *_Nullable __autoreleasing *)error { - return [self.controller.groundOverlaysController groundOverlayWithIdentifier:groundOverlayId]; -} - -- (nullable FGMPlatformCameraPosition *)cameraPosition: - (FlutterError *_Nullable __autoreleasing *_Nonnull)error { - return FGMGetPigeonCameraPositionForPosition(self.controller.mapView.camera); -} - -@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGoogleMapsPlugin.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGoogleMapsPlugin.m deleted file mode 100644 index 072d675b17b8..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGoogleMapsPlugin.m +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "FGMGoogleMapsPlugin.h" - -@import GoogleMaps; - -#pragma mark - GoogleMaps plugin implementation - -// Declares a GMSServices method that was added in SDK 9.2, so that it can be -// conditionally called. It is declared on NSObject to avoid duplicate -// declaration errors when compiling with newer SDKs. -// TODO(stuartmorgan): Remove this once all packages sharing this file require -// SDK 9.2 or later. See https://github.com/flutter/flutter/issues/187106 -@interface NSObject (MapsSDK92Extensions) -+ (void)addInternalUsageAttributionID:(nonnull NSString *)internalUsageAttributionID; -@end - -@implementation FGMGoogleMapsPlugin - -+ (void)registerWithRegistrar:(NSObject *)registrar { - FGMGoogleMapFactory *googleMapFactory = [[FGMGoogleMapFactory alloc] initWithRegistrar:registrar]; - [registrar registerViewFactory:googleMapFactory - withId:@"plugins.flutter.dev/google_maps_ios" - gestureRecognizersBlockingPolicy: - FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded]; - if ([GMSServices respondsToSelector:@selector(addInternalUsageAttributionID:)]) { - [GMSServices addInternalUsageAttributionID:@"gmp_flutter_googlemapsflutter_ios"]; - } -} - -@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.swift b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.swift new file mode 100644 index 000000000000..b5b822b9442b --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.swift @@ -0,0 +1,938 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps +import GoogleMapsUtils + +#if canImport(google_maps_flutter_ios_sdk9_objc) + import google_maps_flutter_ios_sdk9_objc +#endif + +/// Non-test implementation of FGMAssetProvider, wrapping a Flutter plugin registrar. +class DefaultAssetProvider: NSObject, FGMAssetProvider { + weak var registrar: FlutterPluginRegistrar? + + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + super.init() + } + + func lookupKey(forAsset asset: String) -> String? { + return registrar?.lookupKey(forAsset: asset) + } + + func lookupKey(forAsset asset: String, fromPackage package: String) -> String? { + return registrar?.lookupKey(forAsset: asset, fromPackage: package) + } + + func imageNamed(_ name: String) -> UIImage? { + return UIImage(named: name) + } +} + +/// Non-test implementation of FGMMapEventDelegate, wrapping a FGMMapsCallbackApi instance. +class DefaultMapEventHandler: NSObject, FGMMapEventDelegate { + let callbackHandler: FGMMapsCallbackApi + + init(callbackHandler: FGMMapsCallbackApi) { + self.callbackHandler = callbackHandler + super.init() + } + + func didStartCameraMove() { + callbackHandler.didStartCameraMove { _ in } + } + + func didMoveCamera(to cameraPosition: FGMPlatformCameraPosition) { + callbackHandler.didMoveCamera(to: cameraPosition) { _ in } + } + + func didIdleCamera() { + callbackHandler.didIdleCamera { _ in } + } + + func didTap(atPosition position: FGMPlatformLatLng) { + callbackHandler.didTap(atPosition: position) { _ in } + } + + func didLongPress(atPosition position: FGMPlatformLatLng) { + callbackHandler.didLongPress(atPosition: position) { _ in } + } + + func didTapMarker(withIdentifier markerId: String) { + callbackHandler.didTapMarker(withIdentifier: markerId) { _ in } + } + + func didStartDragForMarker( + withIdentifier markerId: String, atPosition position: FGMPlatformLatLng + ) { + callbackHandler.didStartDragForMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didDragMarker(withIdentifier markerId: String, atPosition position: FGMPlatformLatLng) { + callbackHandler.didDragMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didEndDragForMarker(withIdentifier markerId: String, atPosition position: FGMPlatformLatLng) + { + callbackHandler.didEndDragForMarker(withIdentifier: markerId, atPosition: position) { _ in } + } + + func didTapInfoWindowOfMarker(withIdentifier markerId: String) { + callbackHandler.didTapInfoWindowOfMarker(withIdentifier: markerId) { _ in } + } + + func didTapCircle(withIdentifier circleId: String) { + callbackHandler.didTapCircle(withIdentifier: circleId) { _ in } + } + + func didTap(_ cluster: FGMPlatformCluster) { + callbackHandler.didTap(cluster) { _ in } + } + + func didTapPolygon(withIdentifier polygonId: String) { + callbackHandler.didTapPolygon(withIdentifier: polygonId) { _ in } + } + + func didTapPolyline(withIdentifier polylineId: String) { + callbackHandler.didTapPolyline(withIdentifier: polylineId) { _ in } + } + + func didTapGroundOverlay(withIdentifier groundOverlayId: String) { + callbackHandler.didTapGroundOverlay(withIdentifier: groundOverlayId) { _ in } + } +} + +public class GoogleMapController: NSObject, GMSMapViewDelegate, FlutterPlatformView { + /// The Google Maps SDK map view managed by this controller. + let mapView: GMSMapView + /// The Pigeon callback API implementation, used to send events to the Dart side. + let dartCallbackHandler: FGMMapsCallbackApi + /// The map SDK event handler, which routes events to the Dart callback handler. + let mapEventHandler: DefaultMapEventHandler + /// The main Pigeon API implementation, separate to avoid lifetime extension. + let callHandler: MapCallHandler + /// The inspector API implementation, separate to avoid lifetime extension. + let inspector: MapInspector + /// A shim to pass tile requests to `dartCallbackHandler`. This is a separate object to avoid init ordering issues. + private let tileProvider: ConcreteTileProvider + /// Whether to send notifications about camera position changes to Dart. + var trackCameraPosition = false + + /// Sub-controllers for managing individual map features. + let clusterManagersController: FGMClusterManagersController + let markersController: FGMMarkersController + let polygonsController: FGMPolygonsController + let polylinesController: FGMPolylinesController + let circlesController: FGMCirclesController + let heatmapsController: FGMHeatmapsController + let tileOverlaysController: FGMTileOverlaysController + let groundOverlaysController: FGMGroundOverlaysController + + // The resulting error message, if any, from the last attempt to set the map style. + // This is used to provide access to errors after the fact, since the map style is generally set at + // creation time and there's no mechanism to return non-fatal error details during platform view + // initialization. + var styleError: String? + /// Whether we are currently observing the "frame" key path on `mapView`. + private var isObservingFrame = false + + public convenience init( + frame: CGRect, + viewIdentifier viewId: Int64, + creationParameters: FGMPlatformMapViewCreationParams, + registrar: FlutterPluginRegistrar + ) { + let camera = FGMGetCameraPositionForPigeonCameraPosition( + creationParameters.initialCameraPosition) + + let options = GMSMapViewOptions() + options.frame = frame + options.camera = camera + if let mapId = creationParameters.mapConfiguration.mapId, !mapId.isEmpty { + options.mapID = GMSMapID(identifier: mapId) + } + + self.init( + mapView: GMSMapView(options: options), + viewIdentifier: viewId, + creationParameters: creationParameters, + assetProvider: DefaultAssetProvider(registrar: registrar), + binaryMessenger: registrar.messenger() + ) + } + + public init( + mapView: GMSMapView, + viewIdentifier viewId: Int64, + creationParameters: FGMPlatformMapViewCreationParams, + assetProvider: FGMAssetProvider, + binaryMessenger: FlutterBinaryMessenger + ) { + self.mapView = mapView + mapView.accessibilityElementsHidden = false + mapView.paddingAdjustmentBehavior = .never + // The code below must be kept in sync with `interpretMapConfiguration`. The small amount of + // duplication here is to avoid having to defer all map view configuration until after the + // sub-controllers are given the map view. + let (styleUpdateAttempted, errorString) = GoogleMapController.updateMapView( + mapView, fromConfiguration: creationParameters.mapConfiguration) + if styleUpdateAttempted { + styleError = errorString + } + if let trackCameraPosition = creationParameters.mapConfiguration.trackCameraPosition { + self.trackCameraPosition = trackCameraPosition.boolValue + } + // End duplicate code. + + let pigeonSuffix = String(format: "%lld", viewId) + dartCallbackHandler = FGMMapsCallbackApi( + binaryMessenger: binaryMessenger, + messageChannelSuffix: pigeonSuffix + ) + + mapEventHandler = DefaultMapEventHandler(callbackHandler: dartCallbackHandler) + + let markerType = creationParameters.mapConfiguration.markerType + + clusterManagersController = FGMClusterManagersController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + markersController = FGMMarkersController( + mapView: mapView, + eventDelegate: mapEventHandler, + clusterManagersController: clusterManagersController, + assetProvider: assetProvider, + markerType: markerType + ) + polygonsController = FGMPolygonsController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + polylinesController = FGMPolylinesController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + circlesController = FGMCirclesController( + mapView: mapView, + eventDelegate: mapEventHandler + ) + heatmapsController = FGMHeatmapsController(mapView: mapView) + tileProvider = ConcreteTileProvider(dartCallbackHandler: dartCallbackHandler) + tileOverlaysController = FGMTileOverlaysController( + mapView: mapView, + tileProvider: tileProvider + ) + groundOverlaysController = FGMGroundOverlaysController( + mapView: mapView, + eventDelegate: mapEventHandler, + assetProvider: assetProvider + ) + + clusterManagersController.add(creationParameters.initialClusterManagers) + markersController.add(creationParameters.initialMarkers) + polygonsController.add(creationParameters.initialPolygons) + polylinesController.add(creationParameters.initialPolylines) + circlesController.add(creationParameters.initialCircles) + heatmapsController.add(creationParameters.initialHeatmaps) + tileOverlaysController.add(creationParameters.initialTileOverlays) + groundOverlaysController.add(creationParameters.initialGroundOverlays) + + callHandler = MapCallHandler( + messenger: binaryMessenger, + pigeonSuffix: pigeonSuffix + ) + inspector = MapInspector( + messenger: binaryMessenger, + pigeonSuffix: pigeonSuffix + ) + + super.init() + + callHandler.controller = self + SetUpFGMMapsApiWithSuffix(binaryMessenger, callHandler, pigeonSuffix) + inspector.controller = self + SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, inspector, pigeonSuffix) + + mapView.delegate = self + isObservingFrame = true + mapView.addObserver(self, forKeyPath: "frame", options: [], context: nil) + + // Invoke clustering after everything is configured. + clusterManagersController.invokeClusteringForEachClusterManager() + } + + deinit { + if isObservingFrame { + mapView.removeObserver(self, forKeyPath: "frame") + } + SetUpFGMMapsApiWithSuffix(callHandler.messenger, nil, callHandler.pigeonSuffix) + SetUpFGMMapsInspectorApiWithSuffix(inspector.messenger, nil, inspector.pigeonSuffix) + } + + public func view() -> UIView { + return mapView + } + + override public func observeValue( + forKeyPath keyPath: String?, + of object: Any?, + change: [NSKeyValueChangeKey: Any]?, + context: UnsafeMutableRawPointer? + ) { + if let keyPath = keyPath, + let gmsMapView = object as? GMSMapView, + gmsMapView == mapView, + keyPath == "frame" + { + let bounds = mapView.bounds + if bounds.equalTo(.zero) { + // The workaround is to fix an issue that the camera location is not current when + // the size of the map is zero at initialization. + // So We only care about the size of the `self.mapView`, ignore the frame changes when the + // size is zero. + return + } + // We only observe the frame for initial setup. + isObservingFrame = false + mapView.removeObserver(self, forKeyPath: "frame") + mapView.moveCamera(GMSCameraUpdate.setCamera(mapView.camera)) + } else { + super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + } + } + + public func showAtOrigin(_ origin: CGPoint) { + mapView.frame = CGRect(origin: origin, size: mapView.frame.size) + mapView.isHidden = false + } + + public func hide() { + mapView.isHidden = true + } + + public func cameraPosition() -> GMSCameraPosition? { + return trackCameraPosition ? mapView.camera : nil + } + + func setCamera(_ camera: GMSCameraPosition) { + mapView.camera = camera + } + + /// Sets the map style, returning any error string as well as storing that error in `styleError` for + /// later access. + func setMapStyle(_ mapStyle: String) -> String? { + let (style, errorString) = GoogleMapController.parseMapStyle(mapStyle) + if errorString == nil { + mapView.mapStyle = style + } + styleError = errorString + return errorString + } + + /// Attempts to construct a GMSMapStyle from a JSON style string, returning the style, as well as + /// an error string if it the style could not be created. + /// + /// - If the String? value is non-nil, that description of the error should be stored in + /// `styleError` by the caller for later access, and the style should be set on the map. + /// - If the String? value is nil, the style should be set on the map. The style may be nil if + /// the input string is empty, which is how the platform channel expresses clearing the style. + static func parseMapStyle(_ jsonStyle: String) -> (GMSMapStyle?, String?) { + if jsonStyle.isEmpty { + return (nil, nil) + } + do { + let style = try GMSMapStyle(jsonString: jsonStyle) + return (style, nil) + } catch let error { + return (nil, error.localizedDescription) + } + } + + // MARK: - GMSMapViewDelegate methods + + public func mapView(_ mapView: GMSMapView, willMove gesture: Bool) { + mapEventHandler.didStartCameraMove() + } + + public func mapView(_ mapView: GMSMapView, didChange position: GMSCameraPosition) { + if trackCameraPosition { + mapEventHandler.didMoveCamera(to: FGMGetPigeonCameraPositionForPosition(position)) + } + } + + public func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) { + mapEventHandler.didIdleCamera() + } + + public func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { + if let cluster = marker.userData as? GMUStaticCluster { + clusterManagersController.didTap(cluster) + return false + } + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + return markersController.didTapMarker(withIdentifier: markerId) + } + return false + } + + public func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didEndDraggingMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didBeginDragging marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didStartDraggingMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didDrag marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didDragMarker(withIdentifier: markerId, location: marker.position) + } + } + + public func mapView(_ mapView: GMSMapView, didTapInfoWindowOf marker: GMSMarker) { + if let markerId = FGMGetMarkerIdentifierFromMarker(marker) { + markersController.didTapInfoWindowOfMarker(withIdentifier: markerId) + } + } + + public func mapView(_ mapView: GMSMapView, didTap overlay: GMSOverlay) { + guard let userDataArray = overlay.userData as? [Any], + let overlayId = userDataArray.first as? String + else { + return + } + if polylinesController.hasPolyline(withIdentifier: overlayId) == true { + polylinesController.didTapPolyline(withIdentifier: overlayId) + } else if polygonsController.hasPolygon(withIdentifier: overlayId) == true { + polygonsController.didTapPolygon(withIdentifier: overlayId) + } else if circlesController.hasCircle(withIdentifier: overlayId) == true { + circlesController.didTapCircle(withIdentifier: overlayId) + } else if groundOverlaysController.hasGroundOverlays(withIdentifier: overlayId) == true { + groundOverlaysController.didTapGroundOverlay(withIdentifier: overlayId) + } + } + + public func mapView(_ mapView: GMSMapView, didTapAt coordinate: CLLocationCoordinate2D) { + mapEventHandler.didTap(atPosition: FGMGetPigeonLatLngForCoordinate(coordinate)) + } + + public func mapView(_ mapView: GMSMapView, didLongPressAt coordinate: CLLocationCoordinate2D) { + mapEventHandler.didLongPress(atPosition: FGMGetPigeonLatLngForCoordinate(coordinate)) + } + + func interpretMapConfiguration(_ config: FGMPlatformMapConfiguration) { + // Any changes here must also be made to the `init` method above. See the comment there for + // details. + let (styleUpdateAttempted, errorString) = GoogleMapController.updateMapView( + mapView, fromConfiguration: config) + if styleUpdateAttempted { + styleError = errorString + } + if let trackCameraPosition = config.trackCameraPosition { + self.trackCameraPosition = trackCameraPosition.boolValue + } + } + + /// Updates the given map view with new configuration options. + /// + /// Returns a boolean indicating whether a style update was attempted, and an error string + /// describing any error interpreting the style in `config`. If the boolean is true, the error + /// string should be stored in `styleError` for later access. + static func updateMapView( + _ mapView: GMSMapView, fromConfiguration config: FGMPlatformMapConfiguration + ) -> (Bool, String?) { + if let cameraTargetBounds = config.cameraTargetBounds { + if let bounds = cameraTargetBounds.bounds { + mapView.cameraTargetBounds = FGMGetCoordinateBoundsForPigeonLatLngBounds(bounds) + } else { + mapView.cameraTargetBounds = nil + } + } + if let compassEnabled = config.compassEnabled { + mapView.settings.compassButton = compassEnabled.boolValue + } + if let indoorEnabled = config.indoorViewEnabled { + mapView.isIndoorEnabled = indoorEnabled.boolValue + } + if let trafficEnabled = config.trafficEnabled { + mapView.isTrafficEnabled = trafficEnabled.boolValue + } + if let buildingsEnabled = config.buildingsEnabled { + mapView.isBuildingsEnabled = buildingsEnabled.boolValue + } + if let mapType = config.mapType { + mapView.mapType = FGMGetMapViewTypeForPigeonMapType(mapType.value) + } + if let zoomData = config.minMaxZoomPreference { + let minZoom = zoomData.min?.floatValue ?? kGMSMinZoomLevel + let maxZoom = zoomData.max?.floatValue ?? kGMSMaxZoomLevel + mapView.setMinZoom(minZoom, maxZoom: maxZoom) + } + if let padding = config.padding { + mapView.padding = UIEdgeInsets( + top: CGFloat(padding.top), + left: CGFloat(padding.left), + bottom: CGFloat(padding.bottom), + right: CGFloat(padding.right) + ) + } + if let rotateGesturesEnabled = config.rotateGesturesEnabled { + mapView.settings.rotateGestures = rotateGesturesEnabled.boolValue + } + if let scrollGesturesEnabled = config.scrollGesturesEnabled { + mapView.settings.scrollGestures = scrollGesturesEnabled.boolValue + } + if let tiltGesturesEnabled = config.tiltGesturesEnabled { + mapView.settings.tiltGestures = tiltGesturesEnabled.boolValue + } + if let zoomGesturesEnabled = config.zoomGesturesEnabled { + mapView.settings.zoomGestures = zoomGesturesEnabled.boolValue + } + if let myLocationEnabled = config.myLocationEnabled { + mapView.isMyLocationEnabled = myLocationEnabled.boolValue + } + if let myLocationButtonEnabled = config.myLocationButtonEnabled { + mapView.settings.myLocationButton = myLocationButtonEnabled.boolValue + } + if let mapStyle = config.style { + let (style, errorString) = GoogleMapController.parseMapStyle(mapStyle) + if errorString == nil { + mapView.mapStyle = style + } + return (true, errorString) + } + return (false, nil) + } +} + +// TODO(stuartmorgan): Remove this in favor of an extension to add FGMTileProviderDelegate to +// the Pigeon Flutter API object once this plugin has switched to Swift Pigeon generation +// (adjusting the protocol to match the Swift version of the signature). +private class ConcreteTileProvider: NSObject, FGMTileProviderDelegate { + let handler: FGMMapsCallbackApi + + init(dartCallbackHandler: FGMMapsCallbackApi) { + handler = dartCallbackHandler + } + + public func tile( + withOverlayIdentifier tileOverlayId: String, + location: FGMPlatformPoint, + zoom: Int, + completion: @escaping (FGMPlatformTile?, FlutterError?) -> Void + ) { + handler.tile( + withOverlayIdentifier: tileOverlayId, + location: location, + zoom: zoom, + completion: completion + ) + } +} + +class MapCallHandler: NSObject, FGMMapsApi { + weak var controller: GoogleMapController? + let messenger: FlutterBinaryMessenger + let pigeonSuffix: String + var transactionWrapper: FGMCATransactionProtocol + + init( + messenger: FlutterBinaryMessenger, + pigeonSuffix suffix: String + ) { + self.messenger = messenger + self.pigeonSuffix = suffix + self.transactionWrapper = FGMCATransactionWrapper() + super.init() + } + + func waitForMapWithError(_ error: AutoreleasingUnsafeMutablePointer) { + // No-op; this call just ensures synchronization with the platform thread. + } + + func updateCircles( + byAdding toAdd: [FGMPlatformCircle], changing toChange: [FGMPlatformCircle], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.circlesController.add(toAdd) + controller?.circlesController.change(toChange) + controller?.circlesController.removeCircles(withIdentifiers: idsToRemove) + } + + func updateHeatmaps( + byAdding toAdd: [FGMPlatformHeatmap], changing toChange: [FGMPlatformHeatmap], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.heatmapsController.add(toAdd) + controller?.heatmapsController.change(toChange) + controller?.heatmapsController.removeHeatmaps(withIdentifiers: idsToRemove) + } + + func update( + with configuration: FGMPlatformMapConfiguration, + error: AutoreleasingUnsafeMutablePointer + ) { + controller?.interpretMapConfiguration(configuration) + } + + func updateMarkers( + byAdding toAdd: [FGMPlatformMarker], changing toChange: [FGMPlatformMarker], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.add(toAdd) + controller?.markersController.change(toChange) + controller?.markersController.removeMarkers(withIdentifiers: idsToRemove) + controller?.clusterManagersController.invokeClusteringForEachClusterManager() + } + + func updateClusterManagers( + byAdding toAdd: [FGMPlatformClusterManager], removing idsToRemove: [String], + error: AutoreleasingUnsafeMutablePointer + ) { + controller?.clusterManagersController.add(toAdd) + controller?.clusterManagersController.removeClusterManagers(withIdentifiers: idsToRemove) + } + + func updatePolygons( + byAdding toAdd: [FGMPlatformPolygon], changing toChange: [FGMPlatformPolygon], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.polygonsController.add(toAdd) + controller?.polygonsController.change(toChange) + controller?.polygonsController.removePolygon(withIdentifiers: idsToRemove) + } + + func updatePolylines( + byAdding toAdd: [FGMPlatformPolyline], changing toChange: [FGMPlatformPolyline], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.polylinesController.add(toAdd) + controller?.polylinesController.change(toChange) + controller?.polylinesController.removePolyline(withIdentifiers: idsToRemove) + } + + func updateTileOverlays( + byAdding toAdd: [FGMPlatformTileOverlay], changing toChange: [FGMPlatformTileOverlay], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.tileOverlaysController.add(toAdd) + controller?.tileOverlaysController.change(toChange) + controller?.tileOverlaysController.removeTileOverlay(withIdentifiers: idsToRemove) + } + + func updateGroundOverlays( + byAdding toAdd: [FGMPlatformGroundOverlay], changing toChange: [FGMPlatformGroundOverlay], + removing idsToRemove: [String], error: AutoreleasingUnsafeMutablePointer + ) { + controller?.groundOverlaysController.add(toAdd) + controller?.groundOverlaysController.change(toChange) + controller?.groundOverlaysController.removeGroundOverlays(withIdentifiers: idsToRemove) + } + + func latLng( + forScreenCoordinate screenCoordinate: FGMPlatformPoint, + error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformLatLng? { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getLatLng called prior to map initialization", + details: nil + ) + return nil + } + let point = FGMGetCGPointForPigeonPoint(screenCoordinate) + let latlng = mapView.projection.coordinate(for: point) + return FGMGetPigeonLatLngForCoordinate(latlng) + } + + func screenCoordinates( + for latLng: FGMPlatformLatLng, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformPoint? { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getScreenCoordinate called prior to map initialization", + details: nil + ) + return nil + } + let location = FGMGetCoordinateForPigeonLatLng(latLng) + let point = mapView.projection.point(for: location) + return FGMGetPigeonPointForCGPoint(point) + } + + func visibleMapRegion(_ error: AutoreleasingUnsafeMutablePointer) + -> FGMPlatformLatLngBounds? + { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "getVisibleRegion called prior to map initialization", + details: nil + ) + return nil + } + let visibleRegion = mapView.projection.visibleRegion() + let bounds = GMSCoordinateBounds(region: visibleRegion) + return FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds) + } + + func moveCamera( + with cameraUpdate: FGMPlatformCameraUpdate, + error: AutoreleasingUnsafeMutablePointer + ) { + guard let update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate) else { + error.pointee = FlutterError( + code: "Invalid update", + message: "Unrecognized camera update", + details: nil + ) + return + } + controller?.mapView.moveCamera(update) + } + + func animateCamera( + with cameraUpdate: FGMPlatformCameraUpdate, duration durationMilliseconds: NSNumber?, + error: AutoreleasingUnsafeMutablePointer + ) { + guard let update = FGMGetCameraUpdateForPigeonCameraUpdate(cameraUpdate) else { + error.pointee = FlutterError( + code: "Invalid update", + message: "Unrecognized camera update", + details: nil + ) + return + } + let transaction = durationMilliseconds != nil ? transactionWrapper : nil + transaction?.begin() + if let duration = durationMilliseconds { + transaction?.setAnimationDuration(duration.doubleValue / 1000.0) + } + controller?.mapView.animate(with: update) + transaction?.commit() + } + + func currentZoomLevel(_ error: AutoreleasingUnsafeMutablePointer) -> NSNumber? { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.camera.zoom) + } + + func showInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.showMarkerInfoWindow(withIdentifier: markerId, error: error) + } + + func hideInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.markersController.hideMarkerInfoWindow(withIdentifier: markerId, error: error) + } + + func isShowingInfoWindowForMarker( + withIdentifier markerId: String, error: AutoreleasingUnsafeMutablePointer + ) -> NSNumber? { + return controller?.markersController.isInfoWindowShownForMarker( + withIdentifier: markerId, error: error) + } + + func setStyle(_ style: String, error: AutoreleasingUnsafeMutablePointer) -> String? + { + return controller?.setMapStyle(style) + } + + func lastStyleError(_ error: AutoreleasingUnsafeMutablePointer) -> String? { + return controller?.styleError + } + + func clearTileCacheForOverlay( + withIdentifier tileOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) { + controller?.tileOverlaysController.clearTileCache(withIdentifier: tileOverlayId) + } + + func takeSnapshotWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> FlutterStandardTypedData? + { + guard let mapView = controller?.mapView else { + error.pointee = FlutterError( + code: "GoogleMap uninitialized", + message: "takeSnapshot called prior to map initialization", + details: nil + ) + return nil + } + let renderer = UIGraphicsImageRenderer(size: mapView.bounds.size) + let image = renderer.image { context in + mapView.drawHierarchy(in: mapView.bounds, afterScreenUpdates: true) + } + if let imageData = image.pngData() { + return FlutterStandardTypedData(bytes: imageData) + } + return nil + } + + func isAdvancedMarkersAvailable(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return false + } + return NSNumber(value: mapView.mapCapabilities.contains(.advancedMarkers)) + } +} + +class MapInspector: NSObject, FGMMapsInspectorApi { + weak var controller: GoogleMapController? + let messenger: FlutterBinaryMessenger + let pigeonSuffix: String + + init( + messenger: FlutterBinaryMessenger, + pigeonSuffix suffix: String + ) { + self.messenger = messenger + self.pigeonSuffix = suffix + super.init() + } + + func areBuildingsEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.isBuildingsEnabled) + } + + func areRotateGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.rotateGestures) + } + + func areScrollGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.scrollGestures) + } + + func areTiltGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.tiltGestures) + } + + func areZoomGesturesEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.zoomGestures) + } + + func tileOverlay( + withIdentifier tileOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformTileLayer? { + guard let controller = controller, + let layer = controller.tileOverlaysController.tileOverlay(withIdentifier: tileOverlayId)? + .layer + else { + return nil + } + return FGMPlatformTileLayer.make( + withVisible: layer.map != nil, + fadeIn: layer.fadeIn, + opacity: Double(layer.opacity), + zIndex: Int(layer.zIndex) + ) + } + + func heatmap( + withIdentifier heatmapId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformHeatmap? { + return controller?.heatmapsController.heatmap(withIdentifier: heatmapId) + } + + func clusters( + withIdentifier clusterManagerId: String, error: AutoreleasingUnsafeMutablePointer + ) -> [FGMPlatformCluster]? { + return controller?.clusterManagersController.clusters( + withIdentifier: clusterManagerId, error: error) + } + + func isCompassEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.compassButton) + } + + func isMyLocationButtonEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.settings.myLocationButton) + } + + func isTrafficEnabledWithError(_ error: AutoreleasingUnsafeMutablePointer) + -> NSNumber? + { + guard let mapView = controller?.mapView else { + return nil + } + return NSNumber(value: mapView.isTrafficEnabled) + } + + func zoomRange(_ error: AutoreleasingUnsafeMutablePointer) -> FGMPlatformZoomRange? + { + guard let mapView = controller?.mapView else { + return nil + } + return FGMPlatformZoomRange.make( + withMin: NSNumber(value: mapView.minZoom), + max: NSNumber(value: mapView.maxZoom) + ) + } + + func groundOverlay( + withIdentifier groundOverlayId: String, error: AutoreleasingUnsafeMutablePointer + ) -> FGMPlatformGroundOverlay? { + return controller?.groundOverlaysController.groundOverlay(withIdentifier: groundOverlayId) + } + + func cameraPosition(_ error: AutoreleasingUnsafeMutablePointer) + -> FGMPlatformCameraPosition? + { + guard let mapView = controller?.mapView else { + return nil + } + return FGMGetPigeonCameraPositionForPosition(mapView.camera) + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapFactory.swift b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapFactory.swift new file mode 100644 index 000000000000..bbd27c27ee46 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapFactory.swift @@ -0,0 +1,34 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps + +#if canImport(google_maps_flutter_ios_sdk9_objc) + import google_maps_flutter_ios_sdk9_objc +#endif + +class GoogleMapFactory: NSObject, FlutterPlatformViewFactory { + weak var registrar: FlutterPluginRegistrar? + static var sharedMapServices = GMSServices.sharedServices() + init(registrar: FlutterPluginRegistrar) { + self.registrar = registrar + } + + func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) + -> any FlutterPlatformView + { + // Precache shared map services, if needed. Initializing this prepares GMSServices + // on a background thread controlled by the GoogleMaps framework. + _ = GoogleMapFactory.sharedMapServices + + return GoogleMapController( + frame: frame, viewIdentifier: viewId, + creationParameters: args as! FGMPlatformMapViewCreationParams, registrar: registrar!) + } + + func createArgsCodec() -> any FlutterMessageCodec & NSObjectProtocol { + return FGMGetGoogleMapsFlutterPigeonMessagesCodec() + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapsPlugin.swift b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapsPlugin.swift new file mode 100644 index 000000000000..8ca573ad6d9f --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapsPlugin.swift @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import GoogleMaps + +public class GoogleMapsPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let factory = GoogleMapFactory(registrar: registrar) + registrar.register( + factory, + withId: "plugins.flutter.dev/google_maps_ios", + gestureRecognizersBlockingPolicy: + FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded) + GMSServices.addInternalUsageAttributionID("gmp_flutter_googlemapsflutter_ios") + } +} diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapController.h deleted file mode 100644 index b723c8d3658e..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapController.h +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMCATransactionWrapper.h" -#import "FGMCircleController.h" -#import "FGMClusterManagersController.h" -#import "FGMMarkerController.h" -#import "FGMPolygonController.h" -#import "FGMPolylineController.h" -#import "google_maps_flutter_pigeon_messages.g.h" - -NS_ASSUME_NONNULL_BEGIN - -// Defines map overlay controllable from Flutter. -@interface FGMGoogleMapController : NSObject -- (instancetype)initWithFrame:(CGRect)frame - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *)registrar; -- (void)showAtOrigin:(CGPoint)origin; -- (void)hide; -- (nullable GMSCameraPosition *)cameraPosition; -@end - -// Allows the engine to create new Google Map instances. -@interface FGMGoogleMapFactory : NSObject -- (instancetype)initWithRegistrar:(NSObject *)registrar; -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapController_Test.h deleted file mode 100644 index 5e1fa9371b2c..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapController_Test.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMAssetProvider.h" -#import "FGMCATransactionWrapper.h" -#import "FGMGoogleMapController.h" - -NS_ASSUME_NONNULL_BEGIN - -/// Implementation of the Pigeon maps API. -/// -/// This is a separate object from the maps controller because the Pigeon API registration keeps a -/// strong reference to the implementor, but as the FlutterPlatformView, the lifetime of the -/// FGMGoogleMapController instance is what needs to trigger Pigeon unregistration, so can't be -/// the target of the registration. -@interface FGMMapCallHandler : NSObject - -/// The transaction wrapper to use for camera animations. -@property(nonatomic, strong) id transactionWrapper; - -@end - -/// Implementation of the Pigeon maps inspector API. -/// -/// This is a separate object from the maps controller because the Pigeon API registration keeps a -/// strong reference to the implementor, but as the FlutterPlatformView, the lifetime of the -/// FGMGoogleMapController instance is what needs to trigger Pigeon unregistration, so can't be -/// the target of the registration. -@interface FGMMapInspector : NSObject - -/// Initializes a Pigeon API for inpector with a map controller. -- (instancetype)initWithMapController:(nonnull FGMGoogleMapController *)controller - messenger:(NSObject *)messenger - pigeonSuffix:(NSString *)suffix; - -@end - -@interface FGMGoogleMapController (Test) - -/// Initializes a map controller with a concrete map view. -/// -/// @param mapView A map view that will be displayed by the controller -/// @param viewId A unique identifier for the controller. -/// @param creationParameters Parameters for initialising the map view. -/// @param assetProvider The asset provider to use for looking up assets. -/// @param binaryMessenger The binary messenger to use for sending messages to Dart. -- (instancetype)initWithMapView:(GMSMapView *)mapView - viewIdentifier:(int64_t)viewId - creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - assetProvider:(NSObject *)assetProvider - binaryMessenger:(NSObject *)binaryMessenger; - -// The main Pigeon API implementation. -@property(nonatomic, strong, readonly) FGMMapCallHandler *callHandler; - -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapsPlugin.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapsPlugin.h deleted file mode 100644 index ec294eb3d3e9..000000000000 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGoogleMapsPlugin.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import GoogleMaps; - -#import "FGMCircleController.h" -#import "FGMClusterManagersController.h" -#import "FGMGoogleMapController.h" -#import "FGMMarkerController.h" -#import "FGMPolygonController.h" -#import "FGMPolylineController.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface FGMGoogleMapsPlugin : NSObject -@end - -NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMCATransactionWrapper.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMCATransactionWrapper.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMCATransactionWrapper.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMCATransactionWrapper.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMCircleController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMCircleController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMCircleController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMCircleController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMClusterManagersController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMClusterManagersController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMClusterManagersController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMClusterManagersController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMConversionUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMConversionUtils.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMConversionUtils.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMConversionUtils.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMGroundOverlayController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMGroundOverlayController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMHeatmapController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMHeatmapController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMHeatmapController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMHeatmapController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMImageUtils.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMImageUtils.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMMarkerController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMMarkerController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMMarkerController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMMarkerController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMMarkerUserData.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMMarkerUserData.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMMarkerUserData.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMMarkerUserData.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMPolygonController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMPolygonController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMPolygonController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMPolygonController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMPolylineController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMPolylineController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMPolylineController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMTileOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMTileOverlayController.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMTileOverlayController.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/FGMTileOverlayController.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/google_maps_flutter_pigeon_messages.g.m b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/google_maps_flutter_pigeon_messages.g.m similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/google_maps_flutter_pigeon_messages.g.m rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/google_maps_flutter_pigeon_messages.g.m diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMAssetProvider.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMAssetProvider.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMCATransactionWrapper.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMCATransactionWrapper.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMCATransactionWrapper.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMCATransactionWrapper.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMCircleController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMCircleController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMCircleController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMCircleController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMCircleController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMCircleController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMCircleController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMCircleController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMClusterManagersController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMClusterManagersController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMClusterManagersController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMClusterManagersController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMConversionUtils.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMConversionUtils.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMConversionUtils.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMConversionUtils.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMGroundOverlayController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMGroundOverlayController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMGroundOverlayController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMGroundOverlayController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMHeatmapController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMHeatmapController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMHeatmapController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMHeatmapController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMHeatmapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMHeatmapController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMHeatmapController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMHeatmapController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMImageUtils.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMImageUtils.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMImageUtils.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMImageUtils.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMapEventDelegate.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMapEventDelegate.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMarkerController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMarkerController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMarkerController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMarkerController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMarkerController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMarkerController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMarkerController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMarkerController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMarkerUserData.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMarkerUserData.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMarkerUserData.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMMarkerUserData.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolygonController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolygonController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolygonController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolygonController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolygonController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolygonController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolygonController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolygonController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolylineController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolylineController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolylineController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolylineController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolylineController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMPolylineController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMPolylineController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMTileOverlayController.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMTileOverlayController.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMTileOverlayController.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMTileOverlayController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMTileOverlayController_Test.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMTileOverlayController_Test.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/FGMTileOverlayController_Test.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/google_maps_flutter_pigeon_messages.g.h b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/google_maps_flutter_pigeon_messages.g.h similarity index 100% rename from packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/google_maps_flutter_pigeon_messages.g.h rename to packages/google_maps_flutter/google_maps_flutter_ios_shared_code/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios_objc/include/google_maps_flutter_ios_objc/google_maps_flutter_pigeon_messages.g.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/sync_shared_files.dart b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/sync_shared_files.dart index 8711068a5604..5fc97464adb5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/sync_shared_files.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/sync_shared_files.dart @@ -33,7 +33,7 @@ void _syncSharedFiles(Directory packageRoot, String packageName, Directory share .map((e) => p.basename(e.path)) .where( (name) => - name.startsWith('google_maps_flutter_ios') && + name.startsWith('google_maps_flutter_ios_') && name != _sharedSourceRootName && name != packageName, ) @@ -116,8 +116,9 @@ void _syncFile(File source, String destinationPath, String destinationPackageNam ].any((pattern) => source.absolute.path.contains(pattern))) { updatePackageNameInPathReferences(File(destinationPath), destinationPackageName); } - // Native unit tests need to import the Swift package. - if (source.absolute.path.contains('/RunnerTests/')) { + // Native unit tests need to import the Swift package, and the Swift files need to import the + // Obj-C sub-package until the Swift migration is complete. + if (source.absolute.path.contains('/RunnerTests/') || source.absolute.path.endsWith('.swift')) { updatePackageNameInImports(File(destinationPath), destinationPackageName); } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/utils.dart b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/utils.dart index 3fb80a0b7e64..2508a25c786a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/utils.dart +++ b/packages/google_maps_flutter/google_maps_flutter_ios_shared_code/tool/utils.dart @@ -49,9 +49,9 @@ List unexpectedUnsharedSourceFiles( /// Adjusts a package-relative path to account for the package name being part of /// the directory structure for Swift packages. String sharedSourceRelativePathForPackagePath(String packageRelativePath) { - return packageRelativePath.replaceAll( - RegExp(r'/google_maps_flutter_ios[_\w\d]*/'), - '/google_maps_flutter_ios/', + return packageRelativePath.replaceAllMapped( + RegExp(r'/google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?)/'), + (match) => '/google_maps_flutter_ios${match.group(1)}/', ); } @@ -61,7 +61,10 @@ String packageRelativePathForSharedSourceRelativePath( String packageName, String sharedSourceRelativePath, ) { - return sharedSourceRelativePath.replaceAll('/google_maps_flutter_ios/', '/$packageName/'); + return sharedSourceRelativePath.replaceAllMapped( + RegExp(r'/google_maps_flutter_ios((?:_objc)?)/'), + (match) => '/$packageName${match.group(1)}/', + ); } /// Returns the contents of the file with any differences caused only by the @@ -70,7 +73,8 @@ String normalizedFileContents(File file) { return file .readAsStringSync() // Ignore differences caused only by the package name. - .replaceAll(RegExp(r'google_maps_flutter_ios_[\w\d]+'), 'google_maps_flutter_ios') + .replaceAll(RegExp(r'google_maps_flutter_ios_sdk[\d]+'), 'google_maps_flutter_ios') + .replaceAll(RegExp(r'google_maps_flutter_ios_sdk[\d]+_objc'), 'google_maps_flutter_ios_objc') // Package name diffs could change line wrapping, so collapse whitespace. .replaceAll(RegExp(r'[\s\n]+'), ' ') .trim(); @@ -84,7 +88,7 @@ String normalizedFileContents(File file) { /// should be replaced in all files. void updatePackageNameInPathReferences(File file, String packageName) { final String newContents = file.readAsStringSync().replaceAllMapped( - RegExp(r'google_maps_flutter_ios[_\w\d]*([:/])'), + RegExp(r'google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?[:/])'), (match) => '$packageName${match.group(1)}', ); file.writeAsStringSync(newContents); @@ -100,13 +104,16 @@ void updatePackageNameInImports(File file, String packageName) { .readAsStringSync() // Package imports. .replaceAllMapped( - RegExp(r'^(@?(?:testable )?)import google_maps_flutter_ios[_\w\d]*(;?)$', multiLine: true), + RegExp( + r'^(@?(?:testable )?)import google_maps_flutter_ios(?:_sdk\d+)?((?:_objc)?;?)$', + multiLine: true, + ), (match) => '${match.group(1)}import $packageName${match.group(2)}', ) // Bridging header. .replaceAllMapped( - RegExp(r'^#import '#import <$packageName/', + RegExp(r'^#import '#import <$packageName${match.group(1)}/', ); file.writeAsStringSync(newContents); }