From 181bcf99406bc151a0836786fa27a94054235f57 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 22 Jan 2026 09:12:56 -0500 Subject: [PATCH 01/11] Abstract asset lookup --- .../ios/Runner.xcodeproj/project.pbxproj | 6 ++ .../RunnerTests/ExtractIconFromDataTests.m | 98 +++++++++---------- .../FGMClusterManagersControllerTests.m | 7 +- .../GoogleMapsGroundOverlayControllerTests.m | 12 +-- .../GoogleMapsMarkerControllerTests.m | 9 +- .../GoogleMapsPolylineControllerTests.m | 1 - .../example/ios/RunnerTests/GoogleMapsTests.m | 1 - .../ios/RunnerTests/TestAssetProvider.h | 13 +++ .../ios/RunnerTests/TestAssetProvider.m | 37 +++++++ .../FGMGroundOverlayController.m | 24 ++--- .../google_maps_flutter_ios/FGMImageUtils.m | 14 +-- .../FLTGoogleMapTileOverlayController.m | 3 +- .../GoogleMapCircleController.m | 3 +- .../GoogleMapController.m | 49 ++++++++-- .../GoogleMapMarkerController.m | 18 ++-- .../GoogleMapPolygonController.m | 5 +- .../GoogleMapPolylineController.m | 5 +- .../FGMAssetProvider.h | 30 ++++++ .../FGMGroundOverlayController.h | 6 +- .../FGMGroundOverlayController_Test.h | 4 +- .../google_maps_flutter_ios/FGMImageUtils.h | 5 +- .../FLTGoogleMapTileOverlayController.h | 4 +- .../GoogleMapCircleController.h | 3 +- .../GoogleMapMarkerController.h | 3 +- .../GoogleMapMarkerController_Test.h | 2 +- .../GoogleMapPolygonController.h | 3 +- .../GoogleMapPolylineController.h | 3 +- 27 files changed, 231 insertions(+), 137 deletions(-) create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj index 0ed22957bea8..75ee7f770c3c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 339355BD2EB3E56300EBF864 /* GoogleMapsTileOverlayControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 339355BC2EB3E55600EBF864 /* GoogleMapsTileOverlayControllerTests.m */; }; 339355BF2EB535A600EBF864 /* FLTGoogleMapHeatmapControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 339355BE2EB5359B00EBF864 /* FLTGoogleMapHeatmapControllerTests.m */; }; 339DF1F02F1FE49800748863 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 339DF1EF2F1FE49300748863 /* AppDelegate.swift */; }; + 33BF9C6E2F2182DF0005FA15 /* TestAssetProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 33BF9C6D2F2182DB0005FA15 /* TestAssetProvider.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 478116522BEF8F47002F593E /* GoogleMapsPolylineControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 478116512BEF8F47002F593E /* GoogleMapsPolylineControllerTests.m */; }; 528F16832C62941000148160 /* FGMClusterManagersControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 528F16822C62941000148160 /* FGMClusterManagersControllerTests.m */; }; @@ -74,6 +75,8 @@ 339355BE2EB5359B00EBF864 /* FLTGoogleMapHeatmapControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTGoogleMapHeatmapControllerTests.m; sourceTree = ""; }; 339DF1EF2F1FE49300748863 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 339DF1F12F1FE4AD00748863 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 33BF9C6C2F2182CB0005FA15 /* TestAssetProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestAssetProvider.h; sourceTree = ""; }; + 33BF9C6D2F2182DB0005FA15 /* TestAssetProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestAssetProvider.m; sourceTree = ""; }; 3ACE0AFE8D82CD5962486AFD /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 478116512BEF8F47002F593E /* GoogleMapsPolylineControllerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsPolylineControllerTests.m; sourceTree = ""; }; @@ -221,6 +224,8 @@ 339355BC2EB3E55600EBF864 /* GoogleMapsTileOverlayControllerTests.m */, 982F2A6A27BADE17003C81F4 /* PartiallyMockedMapView.h */, 982F2A6B27BADE17003C81F4 /* PartiallyMockedMapView.m */, + 33BF9C6C2F2182CB0005FA15 /* TestAssetProvider.h */, + 33BF9C6D2F2182DB0005FA15 /* TestAssetProvider.m */, F7151F14265D7ED70028CB91 /* Info.plist */, ); path = RunnerTests; @@ -509,6 +514,7 @@ 339355BF2EB535A600EBF864 /* FLTGoogleMapHeatmapControllerTests.m in Sources */, 339355BD2EB3E56300EBF864 /* GoogleMapsTileOverlayControllerTests.m in Sources */, F7151F13265D7ED70028CB91 /* GoogleMapsTests.m in Sources */, + 33BF9C6E2F2182DF0005FA15 /* TestAssetProvider.m in Sources */, 6851F3562835BC180032B7C8 /* FGMConversionsUtilsTests.m in Sources */, 982F2A6C27BADE17003C81F4 /* PartiallyMockedMapView.m in Sources */, 330909FF2D99B7A60077A751 /* GoogleMapsMarkerControllerTests.m in Sources */, diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m index 4d7da98cac59..e0d9da9eeae5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m @@ -6,7 +6,8 @@ @import XCTest; #import -#import + +#import "TestAssetProvider.h" @interface ExtractIconFromDataTests : XCTestCase - (UIImage *)createOnePixelImage; @@ -15,15 +16,16 @@ - (UIImage *)createOnePixelImage; @implementation ExtractIconFromDataTests - (void)testExtractIconFromDataAssetAuto { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; - OCMStub([mockRegistrar lookupKeyForAsset:@"fakeImageNameKey"]).andReturn(@"fakeAssetKey"); - OCMStub(ClassMethod([mockImageClass imageNamed:@"fakeAssetKey"])).andReturn(testImage); + NSString *assetName = @"fakeImageName"; + NSString *assetKey = @"fakeAssetKey"; + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey + forAssetName:assetName]; + OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); FGMPlatformBitmapAssetMap *bitmap = - [FGMPlatformBitmapAssetMap makeWithAssetName:@"fakeImageNameKey" + [FGMPlatformBitmapAssetMap makeWithAssetName:assetName bitmapScaling:FGMPlatformMapBitmapScalingAuto imagePixelRatio:1 width:nil @@ -32,7 +34,7 @@ - (void)testExtractIconFromDataAssetAuto { CGFloat screenScale = 3.0; UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], assetProvider, screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, 1.0); @@ -41,16 +43,17 @@ - (void)testExtractIconFromDataAssetAuto { } - (void)testExtractIconFromDataAssetAutoWithScale { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; - OCMStub([mockRegistrar lookupKeyForAsset:@"fakeImageNameKey"]).andReturn(@"fakeAssetKey"); - OCMStub(ClassMethod([mockImageClass imageNamed:@"fakeAssetKey"])).andReturn(testImage); + NSString *assetName = @"fakeImageName"; + NSString *assetKey = @"fakeAssetKey"; + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey + forAssetName:assetName]; + OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); FGMPlatformBitmapAssetMap *bitmap = - [FGMPlatformBitmapAssetMap makeWithAssetName:@"fakeImageNameKey" + [FGMPlatformBitmapAssetMap makeWithAssetName:assetName bitmapScaling:FGMPlatformMapBitmapScalingAuto imagePixelRatio:10 width:nil @@ -59,7 +62,7 @@ - (void)testExtractIconFromDataAssetAutoWithScale { CGFloat screenScale = 3.0; UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], assetProvider, screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, 10); @@ -68,18 +71,19 @@ - (void)testExtractIconFromDataAssetAutoWithScale { } - (void)testExtractIconFromDataAssetAutoAndSizeWithSameAspectRatio { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; XCTAssertEqual(testImage.scale, 1.0); - OCMStub([mockRegistrar lookupKeyForAsset:@"fakeImageNameKey"]).andReturn(@"fakeAssetKey"); - OCMStub(ClassMethod([mockImageClass imageNamed:@"fakeAssetKey"])).andReturn(testImage); + NSString *assetName = @"fakeImageName"; + NSString *assetKey = @"fakeAssetKey"; + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey + forAssetName:assetName]; + OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); const CGFloat width = 15.0; FGMPlatformBitmapAssetMap *bitmap = - [FGMPlatformBitmapAssetMap makeWithAssetName:@"fakeImageNameKey" + [FGMPlatformBitmapAssetMap makeWithAssetName:assetName bitmapScaling:FGMPlatformMapBitmapScalingAuto imagePixelRatio:1 width:@(width) @@ -88,7 +92,7 @@ - (void)testExtractIconFromDataAssetAutoAndSizeWithSameAspectRatio { CGFloat screenScale = 3.0; UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], assetProvider, screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(testImage.scale, 1.0); @@ -102,18 +106,19 @@ - (void)testExtractIconFromDataAssetAutoAndSizeWithSameAspectRatio { } - (void)testExtractIconFromDataAssetAutoAndSizeWithDifferentAspectRatio { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; - OCMStub([mockRegistrar lookupKeyForAsset:@"fakeImageNameKey"]).andReturn(@"fakeAssetKey"); - OCMStub(ClassMethod([mockImageClass imageNamed:@"fakeAssetKey"])).andReturn(testImage); + NSString *assetName = @"fakeImageName"; + NSString *assetKey = @"fakeAssetKey"; + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey + forAssetName:assetName]; + OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); const CGFloat width = 15.0; const CGFloat height = 45.0; FGMPlatformBitmapAssetMap *bitmap = - [FGMPlatformBitmapAssetMap makeWithAssetName:@"fakeImageNameKey" + [FGMPlatformBitmapAssetMap makeWithAssetName:assetName bitmapScaling:FGMPlatformMapBitmapScalingAuto imagePixelRatio:1 width:@(width) @@ -122,7 +127,7 @@ - (void)testExtractIconFromDataAssetAutoAndSizeWithDifferentAspectRatio { CGFloat screenScale = 3.0; UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], assetProvider, screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, screenScale); XCTAssertEqual(resultImage.size.width, width); @@ -130,16 +135,17 @@ - (void)testExtractIconFromDataAssetAutoAndSizeWithDifferentAspectRatio { } - (void)testExtractIconFromDataAssetNoScaling { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; - OCMStub([mockRegistrar lookupKeyForAsset:@"fakeImageNameKey"]).andReturn(@"fakeAssetKey"); - OCMStub(ClassMethod([mockImageClass imageNamed:@"fakeAssetKey"])).andReturn(testImage); + NSString *assetName = @"fakeImageName"; + NSString *assetKey = @"fakeAssetKey"; + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey + forAssetName:assetName]; + OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); FGMPlatformBitmapAssetMap *bitmap = - [FGMPlatformBitmapAssetMap makeWithAssetName:@"fakeImageNameKey" + [FGMPlatformBitmapAssetMap makeWithAssetName:assetName bitmapScaling:FGMPlatformMapBitmapScalingNone imagePixelRatio:1 width:nil @@ -148,7 +154,7 @@ - (void)testExtractIconFromDataAssetNoScaling { CGFloat screenScale = 3.0; UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], assetProvider, screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, 1.0); @@ -157,8 +163,6 @@ - (void)testExtractIconFromDataAssetNoScaling { } - (void)testExtractIconFromDataBytesAuto { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); UIImage *testImage = [self createOnePixelImage]; NSData *pngData = UIImagePNGRepresentation(testImage); XCTAssertNotNil(pngData); @@ -173,8 +177,8 @@ - (void)testExtractIconFromDataBytesAuto { CGFloat screenScale = 3.0; - UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + UIImage *resultImage = FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], + [[TestAssetProvider alloc] init], screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, 1.0); @@ -183,8 +187,6 @@ - (void)testExtractIconFromDataBytesAuto { } - (void)testExtractIconFromDataBytesAutoWithScaling { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); UIImage *testImage = [self createOnePixelImage]; NSData *pngData = UIImagePNGRepresentation(testImage); XCTAssertNotNil(pngData); @@ -199,8 +201,8 @@ - (void)testExtractIconFromDataBytesAutoWithScaling { CGFloat screenScale = 3.0; - UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + UIImage *resultImage = FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], + [[TestAssetProvider alloc] init], screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, 10); XCTAssertEqual(resultImage.size.width, 0.1); @@ -208,8 +210,6 @@ - (void)testExtractIconFromDataBytesAutoWithScaling { } - (void)testExtractIconFromDataBytesAutoAndSizeWithSameAspectRatio { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); UIImage *testImage = [self createOnePixelImage]; NSData *pngData = UIImagePNGRepresentation(testImage); XCTAssertNotNil(pngData); @@ -226,8 +226,8 @@ - (void)testExtractIconFromDataBytesAutoAndSizeWithSameAspectRatio { CGFloat screenScale = 3.0; - UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + UIImage *resultImage = FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], + [[TestAssetProvider alloc] init], screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(testImage.scale, 1.0); @@ -242,8 +242,6 @@ - (void)testExtractIconFromDataBytesAutoAndSizeWithSameAspectRatio { } - (void)testExtractIconFromDataBytesAutoAndSizeWithDifferentAspectRatio { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); UIImage *testImage = [self createOnePixelImage]; NSData *pngData = UIImagePNGRepresentation(testImage); XCTAssertNotNil(pngData); @@ -260,8 +258,8 @@ - (void)testExtractIconFromDataBytesAutoAndSizeWithDifferentAspectRatio { CGFloat screenScale = 3.0; - UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + UIImage *resultImage = FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], + [[TestAssetProvider alloc] init], screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, screenScale); XCTAssertEqual(resultImage.size.width, width); @@ -269,8 +267,6 @@ - (void)testExtractIconFromDataBytesAutoAndSizeWithDifferentAspectRatio { } - (void)testExtractIconFromDataBytesNoScaling { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); UIImage *testImage = [self createOnePixelImage]; NSData *pngData = UIImagePNGRepresentation(testImage); XCTAssertNotNil(pngData); @@ -285,8 +281,8 @@ - (void)testExtractIconFromDataBytesNoScaling { CGFloat screenScale = 3.0; - UIImage *resultImage = - FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], mockRegistrar, screenScale); + UIImage *resultImage = FGMIconFromBitmap([FGMPlatformBitmap makeWithBitmap:bitmap], + [[TestAssetProvider alloc] init], screenScale); XCTAssertNotNil(resultImage); XCTAssertEqual(resultImage.scale, 1.0); XCTAssertEqual(resultImage.size.width, 1.0); diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m index f9baaa10184b..fc54f52581f9 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m @@ -3,12 +3,14 @@ // found in the LICENSE file. @import google_maps_flutter_ios; +@import Flutter; @import XCTest; @import GoogleMaps; -#import #import + #import "PartiallyMockedMapView.h" +#import "TestAssetProvider.h" @interface FGMClusterManagersControllerTests : XCTestCase @end @@ -16,7 +18,6 @@ @interface FGMClusterManagersControllerTests : XCTestCase @implementation FGMClusterManagersControllerTests - (void)testClustering { - NSObject *registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); CGRect frame = CGRectMake(0, 0, 100, 100); GMSMapViewOptions *mapViewOptions = [[GMSMapViewOptions alloc] init]; @@ -34,7 +35,7 @@ - (void)testClustering { [[FLTMarkersController alloc] initWithMapView:mapView callbackHandler:handler clusterManagersController:clusterManagersController - registrar:registrar]; + assetProvider:[[TestAssetProvider alloc] init]]; // Add cluster managers. NSString *clusterManagerId = @"cm"; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsGroundOverlayControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsGroundOverlayControllerTests.m index 9169d6064956..14a607c8487f 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsGroundOverlayControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsGroundOverlayControllerTests.m @@ -6,8 +6,8 @@ @import XCTest; @import GoogleMaps; -#import #import "PartiallyMockedMapView.h" +#import "TestAssetProvider.h" /// A GMSGroundOverlay that ensures that property updates are made before the map is set. @interface PropertyOrderValidatingGroundOverlay : GMSGroundOverlay { @@ -73,8 +73,6 @@ - (void)testUpdatingGroundOverlayWithPosition { FGMPlatformBitmap *bitmap = [FGMPlatformBitmap makeWithBitmap:[FGMPlatformBitmapDefaultMarker makeWithHue:0]]; - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); FGMPlatformGroundOverlay *platformGroundOverlay = [FGMPlatformGroundOverlay makeWithGroundOverlayId:@"id_1" @@ -90,7 +88,7 @@ - (void)testUpdatingGroundOverlayWithPosition { zoomLevel:@14.0]; [groundOverlayController updateFromPlatformGroundOverlay:platformGroundOverlay - registrar:mockRegistrar + assetProvider:[[TestAssetProvider alloc] init] screenScale:1.0]; XCTAssertNotNil(groundOverlayController.groundOverlay.icon); @@ -129,8 +127,6 @@ - (void)testUpdatingGroundOverlayWithBounds { FGMPlatformBitmap *bitmap = [FGMPlatformBitmap makeWithBitmap:[FGMPlatformBitmapDefaultMarker makeWithHue:0]]; - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); FGMPlatformGroundOverlay *platformGroundOverlay = [FGMPlatformGroundOverlay makeWithGroundOverlayId:@"id_1" @@ -146,7 +142,7 @@ - (void)testUpdatingGroundOverlayWithBounds { zoomLevel:nil]; [groundOverlayController updateFromPlatformGroundOverlay:platformGroundOverlay - registrar:mockRegistrar + assetProvider:[[TestAssetProvider alloc] init] screenScale:1.0]; XCTAssertNotNil(groundOverlayController.groundOverlay.icon); @@ -209,7 +205,7 @@ - (void)testUpdateGroundOverlaySetsVisibilityLast { clickable:YES zoomLevel:nil] withMapView:[GoogleMapsGroundOverlayControllerTests mapView] - registrar:nil + assetProvider:[[TestAssetProvider alloc] init] screenScale:1.0 usingBounds:YES]; XCTAssertTrue(groundOverlay.hasSetMap); diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m index bac3fb2cc84e..2d1a0ef75ce0 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m @@ -6,9 +6,8 @@ @import XCTest; @import GoogleMaps; -#import - #import "PartiallyMockedMapView.h" +#import "TestAssetProvider.h" /// A GMSMarker that ensures that property updates are made before the map is set. @interface PropertyOrderValidatingMarker : GMSMarker { @@ -33,12 +32,10 @@ + (GMSMapView *)mapView { /// /// The mapView should outlive the controller, as the controller keeps a weak reference to it. - (FLTMarkersController *)markersControllerWithMapView:(GMSMapView *)mapView { - NSObject *mockRegistrar = - OCMStrictProtocolMock(@protocol(FlutterPluginRegistrar)); return [[FLTMarkersController alloc] initWithMapView:mapView callbackHandler:[[FGMMapsCallbackApi alloc] init] clusterManagersController:nil - registrar:mockRegistrar]; + assetProvider:[[TestAssetProvider alloc] init]]; } - (FGMPlatformBitmap *)placeholderBitmap { @@ -252,7 +249,7 @@ - (void)testUpdateMarkerSetsVisibilityLast { markerId:@"marker" clusterManagerId:nil] withMapView:[GoogleMapsMarkerControllerTests mapView] - registrar:nil + assetProvider:[[TestAssetProvider alloc] init] screenScale:1 usingOpacityForVisibility:NO]; XCTAssertTrue(marker.hasSetMap); diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsPolylineControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsPolylineControllerTests.m index 19ca6e84a266..a018579c3e18 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsPolylineControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsPolylineControllerTests.m @@ -6,7 +6,6 @@ @import XCTest; @import GoogleMaps; -#import #import "PartiallyMockedMapView.h" /// A GMSPolyline that ensures that property updates are made before the map is set. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m index ecbef7b3924e..98249a978710 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m @@ -7,7 +7,6 @@ @import GoogleMaps; #import -#import "FGMCATransactionWrapper.h" #import "PartiallyMockedMapView.h" @interface FLTGoogleMapFactory (Test) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h new file mode 100644 index 000000000000..b0faf709aff2 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h @@ -0,0 +1,13 @@ +// 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 Foundation; +@import google_maps_flutter_ios; + +/// Fake implementation of FGMAssetProvider. +@interface TestAssetProvider : NSObject +/// Initializes an instance that returns the given key for the given asset name, and nil for any +/// other name. +- (instancetype)initWithKey:(NSString *)key forAssetName:(NSString *)assetName; +@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m new file mode 100644 index 000000000000..98040b3aefd6 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m @@ -0,0 +1,37 @@ +// 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 "TestAssetProvider.h" + +@interface TestAssetProvider () +@property(readonly, nonatomic) NSString *key; +@property(readonly, nonatomic) NSString *assetName; +@end + +@implementation TestAssetProvider + +- (instancetype)initWithKey:(NSString *)key forAssetName:(NSString *)assetName { + self = [super init]; + if (self) { + _key = key; + _assetName = assetName; + } + return self; +} + +- (NSString *)lookupKeyForAsset:(NSString *)asset { + if ([asset isEqualToString:self.assetName]) { + return self.key; + } + return nil; +} + +- (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package { + if ([asset isEqualToString:self.assetName]) { + return self.key; + } + return nil; +} + +@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m index 624f43032c53..d83a14f53a32 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m @@ -36,12 +36,12 @@ - (void)removeGroundOverlay { } - (void)updateFromPlatformGroundOverlay:(FGMPlatformGroundOverlay *)groundOverlay - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale { [FGMGroundOverlayController updateGroundOverlay:self.groundOverlay fromPlatformGroundOverlay:groundOverlay withMapView:self.mapView - registrar:registrar + assetProvider:assetProvider screenScale:screenScale usingBounds:self.createdWithBounds]; } @@ -49,14 +49,14 @@ - (void)updateFromPlatformGroundOverlay:(FGMPlatformGroundOverlay *)groundOverla + (void)updateGroundOverlay:(GMSGroundOverlay *)groundOverlay fromPlatformGroundOverlay:(FGMPlatformGroundOverlay *)platformGroundOverlay withMapView:(GMSMapView *)mapView - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale usingBounds:(BOOL)useBounds { groundOverlay.tappable = platformGroundOverlay.clickable; groundOverlay.zIndex = (int)platformGroundOverlay.zIndex; groundOverlay.anchor = CGPointMake(platformGroundOverlay.anchor.x, platformGroundOverlay.anchor.y); - UIImage *image = FGMIconFromBitmap(platformGroundOverlay.image, registrar, screenScale); + UIImage *image = FGMIconFromBitmap(platformGroundOverlay.image, assetProvider, screenScale); groundOverlay.icon = image; groundOverlay.bearing = platformGroundOverlay.bearing; groundOverlay.opacity = 1.0 - platformGroundOverlay.transparency; @@ -88,8 +88,8 @@ @interface FLTGroundOverlaysController () /// A callback api for the map interactions. @property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; -/// Flutter Plugin Registrar used to load images. -@property(weak, nonatomic) NSObject *registrar; +/// Asset provider used to load images. +@property(weak, nonatomic) NSObject *assetProvider; /// The map view used to generate the controllers. @property(weak, nonatomic) GMSMapView *mapView; @@ -100,13 +100,13 @@ @implementation FLTGroundOverlaysController - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar { + assetProvider:(NSObject *)assetProvider { self = [super init]; if (self) { _callbackHandler = callbackHandler; _mapView = mapView; _groundOverlayControllerByIdentifier = [[NSMutableDictionary alloc] init]; - _registrar = registrar; + _assetProvider = assetProvider; } return self; } @@ -129,7 +129,7 @@ - (void)addGroundOverlays:(NSArray *)groundOverlaysT coordinate:CLLocationCoordinate2DMake( groundOverlay.bounds.southwest.latitude, groundOverlay.bounds.southwest.longitude)] - icon:FGMIconFromBitmap(groundOverlay.image, self.registrar, + icon:FGMIconFromBitmap(groundOverlay.image, self.assetProvider, [self getScreenScale])]; } else { NSAssert(groundOverlay.zoomLevel != nil, @@ -137,7 +137,7 @@ - (void)addGroundOverlays:(NSArray *)groundOverlaysT gmsOverlay = [GMSGroundOverlay groundOverlayWithPosition:CLLocationCoordinate2DMake(groundOverlay.position.latitude, groundOverlay.position.longitude) - icon:FGMIconFromBitmap(groundOverlay.image, self.registrar, + icon:FGMIconFromBitmap(groundOverlay.image, self.assetProvider, [self getScreenScale]) zoomLevel:[groundOverlay.zoomLevel doubleValue]]; } @@ -148,7 +148,7 @@ - (void)addGroundOverlays:(NSArray *)groundOverlaysT isCreatedWithBounds:isCreatedWithBounds]; controller.zoomLevel = groundOverlay.zoomLevel; [controller updateFromPlatformGroundOverlay:groundOverlay - registrar:self.registrar + assetProvider:self.assetProvider screenScale:[self getScreenScale]]; self.groundOverlayControllerByIdentifier[identifier] = controller; } @@ -159,7 +159,7 @@ - (void)changeGroundOverlays:(NSArray *)groundOverla NSString *identifier = groundOverlay.groundOverlayId; FGMGroundOverlayController *controller = self.groundOverlayControllerByIdentifier[identifier]; [controller updateFromPlatformGroundOverlay:groundOverlay - registrar:self.registrar + assetProvider:self.assetProvider screenScale:[self getScreenScale]]; } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m index 7bd5192c2377..9ff89d915628 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +@import Flutter; + #import "FGMImageUtils.h" @import Foundation; @@ -44,7 +46,7 @@ CGFloat screenScale); UIImage *FGMIconFromBitmap(FGMPlatformBitmap *platformBitmap, - NSObject *registrar, CGFloat screenScale) { + NSObject *assetProvider, CGFloat screenScale) { assert(screenScale > 0 && "Screen scale must be greater than 0"); // See comment in messages.dart for why this is so loosely typed. See also // https://github.com/flutter/flutter/issues/117819. @@ -62,16 +64,16 @@ // Refer to the flutter google_maps_flutter_platform_interface package for details. FGMPlatformBitmapAsset *bitmapAsset = bitmap; if (bitmapAsset.pkg) { - image = [UIImage imageNamed:[registrar lookupKeyForAsset:bitmapAsset.name - fromPackage:bitmapAsset.pkg]]; + image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAsset.name + fromPackage:bitmapAsset.pkg]]; } else { - image = [UIImage imageNamed:[registrar lookupKeyForAsset:bitmapAsset.name]]; + image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAsset.name]]; } } else if ([bitmap isKindOfClass:[FGMPlatformBitmapAssetImage class]]) { // Deprecated: This message handling for 'fromAssetImage' has been replaced by 'asset'. // Refer to the flutter google_maps_flutter_platform_interface package for details. FGMPlatformBitmapAssetImage *bitmapAssetImage = bitmap; - image = [UIImage imageNamed:[registrar lookupKeyForAsset:bitmapAssetImage.name]]; + image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAssetImage.name]]; image = scaledImage(image, bitmapAssetImage.scale); } else if ([bitmap isKindOfClass:[FGMPlatformBitmapBytes class]]) { // Deprecated: This message handling for 'fromBytes' has been replaced by 'bytes'. @@ -88,7 +90,7 @@ } else if ([bitmap isKindOfClass:[FGMPlatformBitmapAssetMap class]]) { FGMPlatformBitmapAssetMap *bitmapAssetMap = bitmap; - image = [UIImage imageNamed:[registrar lookupKeyForAsset:bitmapAssetMap.assetName]]; + image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAssetMap.assetName]]; if (bitmapAssetMap.bitmapScaling == FGMPlatformMapBitmapScalingAuto) { NSNumber *width = bitmapAssetMap.width; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m index c4cce14ed247..29cd620343ee 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m @@ -141,8 +141,7 @@ @interface FLTTileOverlaysController () @implementation FLTTileOverlaysController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar { + callbackHandler:(FGMMapsCallbackApi *)callbackHandler { self = [super init]; if (self) { _callbackHandler = callbackHandler; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m index d2d0130dc64a..6fe3518e55af 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m @@ -69,8 +69,7 @@ @interface FLTCirclesController () @implementation FLTCirclesController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar { + callbackHandler:(FGMMapsCallbackApi *)callbackHandler { self = [super init]; if (self) { _callbackHandler = callbackHandler; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m index 0537d48ba9ce..6f15e757f607 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m @@ -7,6 +7,7 @@ #import "GoogleMapController.h" #import "GoogleMapController_Test.h" +#import "FGMAssetProvider.h" #import "FGMConversionUtils.h" #import "FGMGroundOverlayController.h" #import "FGMMarkerUserData.h" @@ -66,6 +67,36 @@ - (instancetype)initWithRegistrar:(NSObject *)registrar #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]; +} + +@end + +#pragma mark - + /// Private declarations of the FGMMapCallHandler. @interface FGMMapCallHandler () - (instancetype)initWithMapController:(nonnull FLTGoogleMapController *)controller @@ -165,31 +196,29 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView _mapView.delegate = self; _mapView.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; _registrar = registrar; + FGMDefaultAssetProvider *assetProvider = + [[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar]; _clusterManagersController = [[FGMClusterManagersController alloc] initWithMapView:_mapView callbackHandler:_dartCallbackHandler]; _markersController = [[FLTMarkersController alloc] initWithMapView:_mapView callbackHandler:_dartCallbackHandler clusterManagersController:_clusterManagersController - registrar:registrar]; + assetProvider:assetProvider]; _polygonsController = [[FLTPolygonsController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler - registrar:registrar]; + callbackHandler:_dartCallbackHandler]; _polylinesController = [[FLTPolylinesController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler - registrar:registrar]; + callbackHandler:_dartCallbackHandler]; _circlesController = [[FLTCirclesController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler - registrar:registrar]; + callbackHandler:_dartCallbackHandler]; _heatmapsController = [[FLTHeatmapsController alloc] initWithMapView:_mapView]; _tileOverlaysController = [[FLTTileOverlaysController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler - registrar:registrar]; + callbackHandler:_dartCallbackHandler]; _groundOverlaysController = [[FLTGroundOverlaysController alloc] initWithMapView:_mapView callbackHandler:_dartCallbackHandler - registrar:registrar]; + assetProvider:assetProvider]; [_clusterManagersController addClusterManagers:creationParameters.initialClusterManagers]; [_markersController addMarkers:creationParameters.initialMarkers]; [_polygonsController addPolygons:creationParameters.initialPolygons]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m index ed3aabd7fc10..7b9e5543238b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m @@ -54,7 +54,7 @@ - (void)removeMarker { } - (void)updateFromPlatformMarker:(FGMPlatformMarker *)platformMarker - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale { self.clusterManagerIdentifier = platformMarker.clusterManagerId; self.consumeTapEvents = platformMarker.consumeTapEvents; @@ -69,7 +69,7 @@ - (void)updateFromPlatformMarker:(FGMPlatformMarker *)platformMarker [FLTGoogleMapMarkerController updateMarker:self.marker fromPlatformMarker:platformMarker withMapView:self.mapView - registrar:registrar + assetProvider:assetProvider screenScale:screenScale usingOpacityForVisibility:useOpacityForVisibility]; } @@ -77,12 +77,12 @@ - (void)updateFromPlatformMarker:(FGMPlatformMarker *)platformMarker + (void)updateMarker:(GMSMarker *)marker fromPlatformMarker:(FGMPlatformMarker *)platformMarker withMapView:(GMSMapView *)mapView - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale usingOpacityForVisibility:(BOOL)useOpacityForVisibility { marker.groundAnchor = FGMGetCGPointForPigeonPoint(platformMarker.anchor); marker.draggable = platformMarker.draggable; - UIImage *image = FGMIconFromBitmap(platformMarker.icon, registrar, screenScale); + UIImage *image = FGMIconFromBitmap(platformMarker.icon, assetProvider, screenScale); marker.icon = image; marker.flat = platformMarker.flat; marker.position = FGMGetCoordinateForPigeonLatLng(platformMarker.position); @@ -112,7 +112,7 @@ @interface FLTMarkersController () @property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; /// Controller for adding/removing/fetching cluster managers @property(weak, nonatomic, nullable) FGMClusterManagersController *clusterManagersController; -@property(weak, nonatomic) NSObject *registrar; +@property(weak, nonatomic) NSObject *assetProvider; @property(weak, nonatomic) GMSMapView *mapView; @end @@ -122,14 +122,14 @@ @implementation FLTMarkersController - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler clusterManagersController:(nullable FGMClusterManagersController *)clusterManagersController - registrar:(NSObject *)registrar { + assetProvider:(NSObject *)assetProvider { self = [super init]; if (self) { _callbackHandler = callbackHandler; _mapView = mapView; _clusterManagersController = clusterManagersController; _markerIdentifierToController = [[NSMutableDictionary alloc] init]; - _registrar = registrar; + _assetProvider = assetProvider; } return self; } @@ -150,7 +150,7 @@ - (void)addMarker:(FGMPlatformMarker *)markerToAdd { markerIdentifier:markerIdentifier mapView:self.mapView]; [controller updateFromPlatformMarker:markerToAdd - registrar:self.registrar + assetProvider:self.assetProvider screenScale:[self getScreenScale]]; if (clusterManagerIdentifier) { GMUClusterManager *clusterManager = @@ -179,7 +179,7 @@ - (void)changeMarker:(FGMPlatformMarker *)markerToChange { NSString *clusterManagerIdentifier = markerToChange.clusterManagerId; NSString *previousClusterManagerIdentifier = [controller clusterManagerIdentifier]; [controller updateFromPlatformMarker:markerToChange - registrar:self.registrar + assetProvider:self.assetProvider screenScale:[self getScreenScale]]; if ([controller.marker conformsToProtocol:@protocol(GMUClusterItem)]) { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m index 12cbfeefecd7..469d61aa1859 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m @@ -71,7 +71,6 @@ @interface FLTPolygonsController () @property(strong, nonatomic) NSMutableDictionary *polygonIdentifierToController; @property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; -@property(weak, nonatomic) NSObject *registrar; @property(weak, nonatomic) GMSMapView *mapView; @end @@ -79,14 +78,12 @@ @interface FLTPolygonsController () @implementation FLTPolygonsController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar { + callbackHandler:(FGMMapsCallbackApi *)callbackHandler { self = [super init]; if (self) { _callbackHandler = callbackHandler; _mapView = mapView; _polygonIdentifierToController = [NSMutableDictionary dictionaryWithCapacity:1]; - _registrar = registrar; } return self; } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m index 63a7f7b7b0fc..4c7923f8cd7d 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m @@ -64,7 +64,6 @@ @interface FLTPolylinesController () @property(strong, nonatomic) NSMutableDictionary *polylineIdentifierToController; @property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; -@property(weak, nonatomic) NSObject *registrar; @property(weak, nonatomic) GMSMapView *mapView; @end @@ -73,14 +72,12 @@ @interface FLTPolylinesController () @implementation FLTPolylinesController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar { + callbackHandler:(FGMMapsCallbackApi *)callbackHandler { self = [super init]; if (self) { _callbackHandler = callbackHandler; _mapView = mapView; _polylineIdentifierToController = [NSMutableDictionary dictionaryWithCapacity:1]; - _registrar = registrar; } return self; } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h new file mode 100644 index 000000000000..696bdef9b555 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h @@ -0,0 +1,30 @@ +// 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 Foundation; + +NS_ASSUME_NONNULL_BEGIN + +/// Protocol for looking up Flutter assets. +/// +/// This is used to allow testing with mock assets without mocking the entire +/// Flutter plugin registrar. +@protocol FGMAssetProvider + +/// Returns the key for the given asset. +/// +/// @param asset The name of the asset. +/// @return The key for the asset, or nil if not found. +- (nullable NSString *)lookupKeyForAsset:(NSString *)asset; + +/// Returns the key for the given asset from the given package. +/// +/// @param asset The name of the asset. +/// @param package The name of the package to load the asset from. +/// @return The key for the asset, or nil if not found. +- (nullable NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController.h index a5297f703b9e..398feb2c6cbc 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController.h @@ -3,11 +3,11 @@ // found in the LICENSE file. @import CoreLocation; -@import Flutter; @import Foundation; @import GoogleMaps; @import UIKit; +#import "FGMAssetProvider.h" #import "google_maps_flutter_pigeon_messages.g.h" NS_ASSUME_NONNULL_BEGIN @@ -37,10 +37,10 @@ NS_ASSUME_NONNULL_BEGIN /// Controller of multiple ground overlays on the map. @interface FLTGroundOverlaysController : NSObject -/// Initializes the controller with a GMSMapView, callback handler and registrar. +/// Initializes the controller with a GMSMapView, callback handler and asset provider. - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar; + assetProvider:(NSObject *)assetProvider; /// Adds ground overlays to the map. - (void)addGroundOverlays:(NSArray *)groundOverlaysToAdd; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController_Test.h index 87123539947d..1c4d062348a5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController_Test.h @@ -12,7 +12,7 @@ /// Function to update the gms ground overlay from platform ground overlay. - (void)updateFromPlatformGroundOverlay:(FGMPlatformGroundOverlay *)groundOverlay - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale; /// Updates the underlying GMSGroundOverlay with the properties from the given @@ -22,7 +22,7 @@ + (void)updateGroundOverlay:(GMSGroundOverlay *)groundOverlay fromPlatformGroundOverlay:(FGMPlatformGroundOverlay *)groundOverlay withMapView:(GMSMapView *)mapView - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale usingBounds:(BOOL)useBounds; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMImageUtils.h index 37a833d79d1e..a8fd0c82c688 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMImageUtils.h @@ -2,16 +2,17 @@ // 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 UIKit; +#import "FGMAssetProvider.h" #import "google_maps_flutter_pigeon_messages.g.h" NS_ASSUME_NONNULL_BEGIN /// Creates a UIImage from Pigeon bitmap. UIImage *_Nullable FGMIconFromBitmap(FGMPlatformBitmap *platformBitmap, - NSObject *registrar, + NSObject *assetProvider, CGFloat screenScale); /// Returns a BOOL indicating whether image is considered scalable with the given scale factor from /// size. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h index 5c1b6e5418e8..71d45e01d09a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h @@ -2,7 +2,6 @@ // 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 "google_maps_flutter_pigeon_messages.g.h" @@ -28,8 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTTileOverlaysController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar; + callbackHandler:(FGMMapsCallbackApi *)callbackHandler; - (void)addTileOverlays:(NSArray *)tileOverlaysToAdd; - (void)changeTileOverlays:(NSArray *)tileOverlaysToChange; - (void)removeTileOverlayWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h index 0cb21d926f6a..9ba10f7dacb4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h @@ -18,8 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTCirclesController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar; + callbackHandler:(FGMMapsCallbackApi *)callbackHandler; - (void)addCircles:(NSArray *)circlesToAdd; - (void)changeCircles:(NSArray *)circlesToChange; - (void)removeCirclesWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h index dcebcb1e2982..5222c558fde1 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h @@ -5,6 +5,7 @@ @import Flutter; @import GoogleMaps; +#import "FGMAssetProvider.h" #import "FGMClusterManagersController.h" #import "GoogleMapController.h" #import "google_maps_flutter_pigeon_messages.g.h" @@ -27,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithMapView:(GMSMapView *)mapView callbackHandler:(FGMMapsCallbackApi *)callbackHandler clusterManagersController:(nullable FGMClusterManagersController *)clusterManagersController - registrar:(NSObject *)registrar; + assetProvider:(NSObject *)assetProvider; - (void)addMarkers:(NSArray *)markersToAdd; - (void)changeMarkers:(NSArray *)markersToChange; - (void)removeMarkersWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController_Test.h index f6ff32e791e1..d7a9c1578432 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController_Test.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController_Test.h @@ -16,7 +16,7 @@ + (void)updateMarker:(GMSMarker *)marker fromPlatformMarker:(FGMPlatformMarker *)platformMarker withMapView:(GMSMapView *)mapView - registrar:(NSObject *)registrar + assetProvider:(NSObject *)assetProvider screenScale:(CGFloat)screenScale usingOpacityForVisibility:(BOOL)useOpacityForVisibility; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h index b26cf2416c5f..bd2e78fd9627 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h @@ -17,8 +17,7 @@ @interface FLTPolygonsController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar; + callbackHandler:(FGMMapsCallbackApi *)callbackHandler; - (void)addPolygons:(NSArray *)polygonsToAdd; - (void)changePolygons:(NSArray *)polygonsToChange; - (void)removePolygonWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h index 5505ec54019b..b500c86975f5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h @@ -17,8 +17,7 @@ @interface FLTPolylinesController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler - registrar:(NSObject *)registrar; + callbackHandler:(FGMMapsCallbackApi *)callbackHandler; - (void)addPolylines:(NSArray *)polylinesToAdd; - (void)changePolylines:(NSArray *)polylinesToChange; - (void)removePolylineWithIdentifiers:(NSArray *)identifiers; From 4981e496a1a10b9f17439e24dbfec3518f346d64 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 22 Jan 2026 13:32:35 -0500 Subject: [PATCH 02/11] Wrap UIImage imageNamed: --- .../RunnerTests/ExtractIconFromDataTests.m | 42 +++++++------------ .../ios/RunnerTests/TestAssetProvider.h | 13 ++++-- .../ios/RunnerTests/TestAssetProvider.m | 25 ++++++++--- .../google_maps_flutter_ios/FGMImageUtils.m | 10 ++--- .../GoogleMapController.m | 4 ++ .../FGMAssetProvider.h | 18 ++++++-- 6 files changed, 68 insertions(+), 44 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m index e0d9da9eeae5..4fc1e9eef7d5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/ExtractIconFromDataTests.m @@ -5,8 +5,6 @@ @import google_maps_flutter_ios; @import XCTest; -#import - #import "TestAssetProvider.h" @interface ExtractIconFromDataTests : XCTestCase @@ -16,13 +14,11 @@ - (UIImage *)createOnePixelImage; @implementation ExtractIconFromDataTests - (void)testExtractIconFromDataAssetAuto { - id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; NSString *assetName = @"fakeImageName"; - NSString *assetKey = @"fakeAssetKey"; - TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey - forAssetName:assetName]; - OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithImage:testImage + forAssetName:assetName + package:nil]; FGMPlatformBitmapAssetMap *bitmap = [FGMPlatformBitmapAssetMap makeWithAssetName:assetName @@ -43,14 +39,12 @@ - (void)testExtractIconFromDataAssetAuto { } - (void)testExtractIconFromDataAssetAutoWithScale { - id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; NSString *assetName = @"fakeImageName"; - NSString *assetKey = @"fakeAssetKey"; - TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey - forAssetName:assetName]; - OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithImage:testImage + forAssetName:assetName + package:nil]; FGMPlatformBitmapAssetMap *bitmap = [FGMPlatformBitmapAssetMap makeWithAssetName:assetName @@ -71,15 +65,13 @@ - (void)testExtractIconFromDataAssetAutoWithScale { } - (void)testExtractIconFromDataAssetAutoAndSizeWithSameAspectRatio { - id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; XCTAssertEqual(testImage.scale, 1.0); NSString *assetName = @"fakeImageName"; - NSString *assetKey = @"fakeAssetKey"; - TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey - forAssetName:assetName]; - OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithImage:testImage + forAssetName:assetName + package:nil]; const CGFloat width = 15.0; FGMPlatformBitmapAssetMap *bitmap = @@ -106,14 +98,12 @@ - (void)testExtractIconFromDataAssetAutoAndSizeWithSameAspectRatio { } - (void)testExtractIconFromDataAssetAutoAndSizeWithDifferentAspectRatio { - id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; NSString *assetName = @"fakeImageName"; - NSString *assetKey = @"fakeAssetKey"; - TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey - forAssetName:assetName]; - OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithImage:testImage + forAssetName:assetName + package:nil]; const CGFloat width = 15.0; const CGFloat height = 45.0; @@ -135,14 +125,12 @@ - (void)testExtractIconFromDataAssetAutoAndSizeWithDifferentAspectRatio { } - (void)testExtractIconFromDataAssetNoScaling { - id mockImageClass = OCMClassMock([UIImage class]); UIImage *testImage = [self createOnePixelImage]; NSString *assetName = @"fakeImageName"; - NSString *assetKey = @"fakeAssetKey"; - TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithKey:assetKey - forAssetName:assetName]; - OCMStub(ClassMethod([mockImageClass imageNamed:assetKey])).andReturn(testImage); + TestAssetProvider *assetProvider = [[TestAssetProvider alloc] initWithImage:testImage + forAssetName:assetName + package:nil]; FGMPlatformBitmapAssetMap *bitmap = [FGMPlatformBitmapAssetMap makeWithAssetName:assetName diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h index b0faf709aff2..165ba0b0dc5b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h @@ -7,7 +7,14 @@ /// Fake implementation of FGMAssetProvider. @interface TestAssetProvider : NSObject -/// Initializes an instance that returns the given key for the given asset name, and nil for any -/// other name. -- (instancetype)initWithKey:(NSString *)key forAssetName:(NSString *)assetName; +/// Initializes an instance that returns an arbitrary key for the given asset +/// name, and the given image when when using that key for imageNamed:. +/// +/// Returns nil for any other names. +/// +/// This is useful for setting up tests that need to stub out the standard +/// flow of name -> key -> image. +- (instancetype)initWithImage:(UIImage *)image + forAssetName:(NSString *)assetName + package:(nullable NSString *)package; @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m index 98040b3aefd6..da74d716c1b6 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.m @@ -4,32 +4,45 @@ #import "TestAssetProvider.h" +static NSString *const kTestAssetKey = @"testAssetKey"; + @interface TestAssetProvider () -@property(readonly, nonatomic) NSString *key; +@property(readonly, nonatomic) UIImage *image; @property(readonly, nonatomic) NSString *assetName; +@property(readonly, nonatomic) NSString *package; @end @implementation TestAssetProvider -- (instancetype)initWithKey:(NSString *)key forAssetName:(NSString *)assetName { +- (instancetype)initWithImage:(UIImage *)image + forAssetName:(NSString *)assetName + package:(nullable NSString *)package { self = [super init]; if (self) { - _key = key; + _image = image; _assetName = assetName; + _package = package; } return self; } - (NSString *)lookupKeyForAsset:(NSString *)asset { if ([asset isEqualToString:self.assetName]) { - return self.key; + return kTestAssetKey; } return nil; } - (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package { - if ([asset isEqualToString:self.assetName]) { - return self.key; + if ([asset isEqualToString:self.assetName] && [package isEqualToString:self.package]) { + return kTestAssetKey; + } + return nil; +} + +- (UIImage *)imageNamed:(NSString *)name { + if ([name isEqualToString:kTestAssetKey]) { + return self.image; } return nil; } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m index 9ff89d915628..8136bfd6f6e9 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMImageUtils.m @@ -64,16 +64,16 @@ // Refer to the flutter google_maps_flutter_platform_interface package for details. FGMPlatformBitmapAsset *bitmapAsset = bitmap; if (bitmapAsset.pkg) { - image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAsset.name - fromPackage:bitmapAsset.pkg]]; + image = [assetProvider imageNamed:[assetProvider lookupKeyForAsset:bitmapAsset.name + fromPackage:bitmapAsset.pkg]]; } else { - image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAsset.name]]; + image = [assetProvider imageNamed:[assetProvider lookupKeyForAsset:bitmapAsset.name]]; } } else if ([bitmap isKindOfClass:[FGMPlatformBitmapAssetImage class]]) { // Deprecated: This message handling for 'fromAssetImage' has been replaced by 'asset'. // Refer to the flutter google_maps_flutter_platform_interface package for details. FGMPlatformBitmapAssetImage *bitmapAssetImage = bitmap; - image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAssetImage.name]]; + image = [assetProvider imageNamed:[assetProvider lookupKeyForAsset:bitmapAssetImage.name]]; image = scaledImage(image, bitmapAssetImage.scale); } else if ([bitmap isKindOfClass:[FGMPlatformBitmapBytes class]]) { // Deprecated: This message handling for 'fromBytes' has been replaced by 'bytes'. @@ -90,7 +90,7 @@ } else if ([bitmap isKindOfClass:[FGMPlatformBitmapAssetMap class]]) { FGMPlatformBitmapAssetMap *bitmapAssetMap = bitmap; - image = [UIImage imageNamed:[assetProvider lookupKeyForAsset:bitmapAssetMap.assetName]]; + image = [assetProvider imageNamed:[assetProvider lookupKeyForAsset:bitmapAssetMap.assetName]]; if (bitmapAssetMap.bitmapScaling == FGMPlatformMapBitmapScalingAuto) { NSNumber *width = bitmapAssetMap.width; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m index 6f15e757f607..e13499b110dd 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m @@ -93,6 +93,10 @@ - (NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)packag return [self.registrar lookupKeyForAsset:asset fromPackage:package]; } +- (UIImage *)imageNamed:(NSString *)name { + return [UIImage imageNamed:name]; +} + @end #pragma mark - diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h index 696bdef9b555..2254ec7287b8 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMAssetProvider.h @@ -2,29 +2,41 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@import Foundation; +@import UIKit; NS_ASSUME_NONNULL_BEGIN -/// Protocol for looking up Flutter assets. +/// Protocol for looking up Flutter assets and resolving them to images. /// /// This is used to allow testing with mock assets without mocking the entire -/// Flutter plugin registrar. +/// Flutter plugin registrar and UIImage class. @protocol FGMAssetProvider /// Returns the key for the given asset. /// +/// Wraps the FlutterPluginRegistrar method of the same name. +/// /// @param asset The name of the asset. /// @return The key for the asset, or nil if not found. - (nullable NSString *)lookupKeyForAsset:(NSString *)asset; /// Returns the key for the given asset from the given package. /// +/// Wraps the FlutterPluginRegistrar method of the same name. +/// /// @param asset The name of the asset. /// @param package The name of the package to load the asset from. /// @return The key for the asset, or nil if not found. - (nullable NSString *)lookupKeyForAsset:(NSString *)asset fromPackage:(NSString *)package; +/// Returns the image for the given named asset. +/// +/// Wraps the UIImage method of the same name. +/// +/// @param name The name of the image asset or file. +/// @return The image, or nil if not found. +- (nullable UIImage *)imageNamed:(NSString *)name; + @end NS_ASSUME_NONNULL_END From bc5fd4609b761aaf0320f0cf8d2b10a3a9db92f8 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 22 Jan 2026 16:47:44 -0500 Subject: [PATCH 03/11] Remove mock-based camera update testing --- .../RunnerTests/FGMConversionsUtilsTests.m | 105 ++++++++---------- 1 file changed, 44 insertions(+), 61 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m index ea39943cf571..482089df161e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m @@ -6,7 +6,6 @@ @import XCTest; @import GoogleMaps; -#import #import "PartiallyMockedMapView.h" @interface FGMConversionUtilsTests : XCTestCase @@ -193,7 +192,6 @@ - (void)testMapViewTypeFromPigeonType { } - (void)testCameraUpdateFromNewCameraPosition { - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMPlatformCameraUpdateNewCameraPosition *newPositionUpdate = [FGMPlatformCameraUpdateNewCameraPosition makeWithCameraPosition:[FGMPlatformCameraPosition @@ -204,26 +202,13 @@ - (void)testCameraUpdateFromNewCameraPosition { zoom:3]]; FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:newPositionUpdate]); - [[classMockCameraUpdate expect] - setCamera:FGMGetCameraPositionForPigeonCameraPosition(newPositionUpdate.cameraPosition)]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } -// TODO(cyanglaz): Fix the test for cameraUpdateFromArray with the "NewLatlng" key. -// 2 approaches have been tried and neither worked for the tests. -// -// 1. Use OCMock to vefiry that [GMSCameraUpdate setTarget:] is triggered with the correct value. -// This class method conflicts with certain category method in OCMock, causing OCMock not able to -// disambigious them. -// -// 2. Directly verify the GMSCameraUpdate object returned by the method. -// The GMSCameraUpdate object returned from the method doesn't have any accessors to the "target" -// property. It can be used to update the "camera" property in GMSMapView. However, [GMSMapView -// moveCamera:] doesn't update the camera immediately. Thus the GMSCameraUpdate object cannot be -// verified. -// -// The code in below test uses the 2nd approach. -- (void)skip_testCameraUpdateFromNewLatLong { +- (void)testCameraUpdateFromNewLatLong { const CGFloat lat = 1; const CGFloat lng = 2; FGMPlatformCameraUpdateNewLatLng *platformUpdate = [FGMPlatformCameraUpdateNewLatLng @@ -231,17 +216,10 @@ - (void)skip_testCameraUpdateFromNewLatLong { GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init]; - options.frame = CGRectZero; - options.camera = [GMSCameraPosition cameraWithTarget:CLLocationCoordinate2DMake(5, 6) zoom:1]; - GMSMapView *mapView = [[GMSMapView alloc] initWithOptions:options]; - [mapView moveCamera:update]; - const CGFloat accuracy = 0.001; - XCTAssertEqualWithAccuracy(mapView.camera.target.latitude, lat, - accuracy); // mapView.camera.target.latitude is still 5. - XCTAssertEqualWithAccuracy(mapView.camera.target.longitude, lng, - accuracy); // mapView.camera.target.longitude is still 6. + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromNewLatLngBounds { @@ -254,12 +232,12 @@ - (void)testCameraUpdateFromNewLatLngBounds { FGMPlatformCameraUpdateNewLatLngBounds *platformUpdate = [FGMPlatformCameraUpdateNewLatLngBounds makeWithBounds:FGMGetPigeonLatLngBoundsForCoordinateBounds(bounds) padding:padding]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] fitBounds:bounds withPadding:padding]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromNewLatLngZoom { @@ -270,12 +248,12 @@ - (void)testCameraUpdateFromNewLatLngZoom { makeWithLatLng:[FGMPlatformLatLng makeWithLatitude:lat longitude:lng] zoom:zoom]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] setTarget:CLLocationCoordinate2DMake(lat, lng) zoom:zoom]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromScrollBy { @@ -284,12 +262,12 @@ - (void)testCameraUpdateFromScrollBy { FGMPlatformCameraUpdateScrollBy *platformUpdate = [FGMPlatformCameraUpdateScrollBy makeWithDx:x dy:y]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] scrollByX:x Y:y]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromZoomBy { @@ -297,12 +275,16 @@ - (void)testCameraUpdateFromZoomBy { FGMPlatformCameraUpdateZoomBy *platformUpdateNoPoint = [FGMPlatformCameraUpdateZoomBy makeWithAmount:zoom focus:nil]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdateNoPoint]); + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. +} - [[classMockCameraUpdate expect] zoomBy:zoom]; - +- (void)testCameraUpdateFromZoomByWithFocus { + const CGFloat zoom = 1; const CGFloat x = 2; const CGFloat y = 3; FGMPlatformCameraUpdateZoomBy *platformUpdate = @@ -310,43 +292,44 @@ - (void)testCameraUpdateFromZoomBy { FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] zoomBy:zoom atPoint:CGPointMake(x, y)]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromZoomIn { FGMPlatformCameraUpdateZoom *platformUpdate = [FGMPlatformCameraUpdateZoom makeWithOut:NO]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] zoomIn]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromZoomOut { FGMPlatformCameraUpdateZoom *platformUpdate = [FGMPlatformCameraUpdateZoom makeWithOut:YES]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] zoomOut]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testCameraUpdateFromZoomTo { const CGFloat zoom = 1; FGMPlatformCameraUpdateZoomTo *platformUpdate = [FGMPlatformCameraUpdateZoomTo makeWithZoom:zoom]; - id classMockCameraUpdate = OCMClassMock([GMSCameraUpdate class]); FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); - - [[classMockCameraUpdate expect] zoomTo:zoom]; - [classMockCameraUpdate stopMocking]; + // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath + // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that + // injecting a wrapper would not meaningfully improve test coverage, since the non-test + // implementation would be about as complex as the conversion function itself. } - (void)testStrokeStylesFromPatterns { From 87cae17c155c498bfa318a587881a99a239ffeb5 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 23 Jan 2026 10:56:45 -0500 Subject: [PATCH 04/11] Add a protocol for tile provider to remove OCMock requirement --- .../FLTTileProviderControllerTests.m | 56 ++++++++++++++----- .../FLTGoogleMapTileOverlayController.m | 16 +++--- .../GoogleMapController.m | 20 +++++-- .../FLTGoogleMapTileOverlayController.h | 15 ++++- 4 files changed, 79 insertions(+), 28 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FLTTileProviderControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FLTTileProviderControllerTests.m index 3c7f43b3c206..0040fce6b44b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FLTTileProviderControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FLTTileProviderControllerTests.m @@ -6,7 +6,44 @@ @import GoogleMaps; @import google_maps_flutter_ios; -#import +@interface StubTileReceiver : NSObject +@end + +@implementation StubTileReceiver +- (void)receiveTileWithX:(NSUInteger)x + y:(NSUInteger)y + zoom:(NSUInteger)zoom + image:(nullable UIImage *)image { + // No-op. +} +@end + +@interface TestTileProvider : NSObject +@property(nonatomic) XCTestExpectation *expectation; +@end + +// A tile provider that expects a single call to +// tileWithOverlayIdentifier:location:zoom:completion: on the main thread, +// and then fulfills the expectation. +@implementation TestTileProvider +- (instancetype)initWithExpectation:(XCTestExpectation *)expectation { + if (self = [super init]) { + _expectation = expectation; + } + return self; +} + +- (void)tileWithOverlayIdentifier:(NSString *)tileOverlayId + location:(FGMPlatformPoint *)location + zoom:(NSInteger)zoom + completion:(void (^)(FGMPlatformTile *_Nullable, + FlutterError *_Nullable))completion { + XCTAssertTrue([[NSThread currentThread] isMainThread]); + [self.expectation fulfill]; +} +@end + +#pragma mark - @interface FLTTileProviderControllerTests : XCTestCase @end @@ -14,22 +51,13 @@ @interface FLTTileProviderControllerTests : XCTestCase @implementation FLTTileProviderControllerTests - (void)testCallChannelOnPlatformThread { - id handler = OCMClassMock([FGMMapsCallbackApi class]); + XCTestExpectation *expectation = [self expectationWithDescription:@"invokeMethod"]; + TestTileProvider *tileProvider = [[TestTileProvider alloc] initWithExpectation:expectation]; FLTTileProviderController *controller = [[FLTTileProviderController alloc] initWithTileOverlayIdentifier:@"foo" - callbackHandler:handler]; + tileProvider:tileProvider]; XCTAssertNotNil(controller); - XCTestExpectation *expectation = [self expectationWithDescription:@"invokeMethod"]; - OCMStub([handler tileWithOverlayIdentifier:[OCMArg any] - location:[OCMArg any] - zoom:0 - completion:[OCMArg any]]) - .andDo(^(NSInvocation *invocation) { - XCTAssertTrue([[NSThread currentThread] isMainThread]); - [expectation fulfill]; - }); - id receiver = OCMProtocolMock(@protocol(GMSTileReceiver)); - [controller requestTileForX:0 y:0 zoom:0 receiver:receiver]; + [controller requestTileForX:0 y:0 zoom:0 receiver:[[StubTileReceiver alloc] init]]; [self waitForExpectations:@[ expectation ] timeout:10.0]; } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m index 29cd620343ee..4116c82e4115 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.m @@ -60,17 +60,17 @@ + (void)updateTileLayer:(GMSTileLayer *)tileLayer @interface FLTTileProviderController () -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(weak, nonatomic) NSObject *tileProviderDelegate; @end @implementation FLTTileProviderController - (instancetype)initWithTileOverlayIdentifier:(NSString *)identifier - callbackHandler:(FGMMapsCallbackApi *)callbackHandler { + tileProvider:(NSObject *)tileProvider { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _tileProviderDelegate = tileProvider; _tileOverlayIdentifier = identifier; } return self; @@ -107,7 +107,7 @@ - (void)requestTileForX:(NSUInteger)x zoom:(NSUInteger)zoom receiver:(id)receiver { dispatch_async(dispatch_get_main_queue(), ^{ - [self.callbackHandler + [self.tileProviderDelegate tileWithOverlayIdentifier:self.tileOverlayIdentifier location:[FGMPlatformPoint makeWithX:x y:y] zoom:zoom @@ -133,7 +133,7 @@ @interface FLTTileOverlaysController () @property(strong, nonatomic) NSMutableDictionary *tileOverlayIdentifierToController; -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(weak, nonatomic) NSObject *tileProviderDelegate; @property(weak, nonatomic) GMSMapView *mapView; @end @@ -141,11 +141,11 @@ @interface FLTTileOverlaysController () @implementation FLTTileOverlaysController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler { + tileProvider:(NSObject *)tileProvider { self = [super init]; if (self) { - _callbackHandler = callbackHandler; _mapView = mapView; + _tileProviderDelegate = tileProvider; _tileOverlayIdentifierToController = [[NSMutableDictionary alloc] init]; } return self; @@ -156,7 +156,7 @@ - (void)addTileOverlays:(NSArray *)tileOverlaysToAdd { NSString *identifier = tileOverlay.tileOverlayId; FLTTileProviderController *tileProvider = [[FLTTileProviderController alloc] initWithTileOverlayIdentifier:identifier - callbackHandler:self.callbackHandler]; + tileProvider:self.tileProviderDelegate]; FLTGoogleMapTileOverlayController *controller = [[FLTGoogleMapTileOverlayController alloc] initWithTileOverlay:tileOverlay tileLayer:tileProvider diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m index e13499b110dd..9e84b1285016 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m @@ -130,7 +130,7 @@ @interface FGMMapInspector () #pragma mark - -@interface FLTGoogleMapController () +@interface FLTGoogleMapController () @property(nonatomic, strong) GMSMapView *mapView; @property(nonatomic, strong) FGMMapsCallbackApi *dartCallbackHandler; @@ -216,9 +216,8 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView _circlesController = [[FLTCirclesController alloc] initWithMapView:_mapView callbackHandler:_dartCallbackHandler]; _heatmapsController = [[FLTHeatmapsController alloc] initWithMapView:_mapView]; - _tileOverlaysController = - [[FLTTileOverlaysController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler]; + _tileOverlaysController = [[FLTTileOverlaysController alloc] initWithMapView:_mapView + tileProvider:self]; _groundOverlaysController = [[FLTGroundOverlaysController alloc] initWithMapView:_mapView callbackHandler:_dartCallbackHandler @@ -533,6 +532,19 @@ - (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { } } +#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 - diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h index 71d45e01d09a..20417e07b74a 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h @@ -8,6 +8,17 @@ NS_ASSUME_NONNULL_BEGIN +/// Protocol for requesting tiles from the Dart side. +@protocol FGMTileProviderDelegate +- (void)tileWithOverlayIdentifier:(NSString *)tileOverlayId + location:(FGMPlatformPoint *)location + zoom:(NSInteger)zoom + completion:(void (^)(FGMPlatformTile *_Nullable, + FlutterError *_Nullable))completion; +@end + +#pragma mark - + @interface FLTGoogleMapTileOverlayController : NSObject /// The layer managed by this controller instance. @property(readonly, nonatomic) GMSTileLayer *layer; @@ -22,12 +33,12 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTTileProviderController : GMSTileLayer @property(copy, nonatomic, readonly) NSString *tileOverlayIdentifier; - (instancetype)initWithTileOverlayIdentifier:(NSString *)identifier - callbackHandler:(FGMMapsCallbackApi *)callbackHandler; + tileProvider:(NSObject *)tileProvider; @end @interface FLTTileOverlaysController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler; + tileProvider:(NSObject *)tileProvider; - (void)addTileOverlays:(NSArray *)tileOverlaysToAdd; - (void)changeTileOverlays:(NSArray *)tileOverlaysToChange; - (void)removeTileOverlayWithIdentifiers:(NSArray *)identifiers; From 23e65c0565c64802e71f9b76978c08dd2a3097e7 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 23 Jan 2026 13:54:53 -0500 Subject: [PATCH 05/11] Switch to a generalized event delegate --- .../ios/Runner.xcodeproj/project.pbxproj | 8 + .../FGMClusterManagersControllerTests.m | 10 +- .../RunnerTests/FGMConversionsUtilsTests.m | 2 +- .../GoogleMapsMarkerControllerTests.m | 27 +++- .../ios/RunnerTests/TestAssetProvider.h | 6 +- .../ios/RunnerTests/TestMapEventHandler.h | 14 ++ .../ios/RunnerTests/TestMapEventHandler.m | 56 +++++++ .../FGMClusterManagersController.m | 12 +- .../FGMGroundOverlayController.m | 10 +- .../GoogleMapCircleController.m | 10 +- .../GoogleMapController.m | 149 +++++++++++++++--- .../GoogleMapMarkerController.m | 35 ++-- .../GoogleMapPolygonController.m | 10 +- .../GoogleMapPolylineController.m | 10 +- .../FGMClusterManagersController.h | 5 +- .../FGMConversionUtils.h | 1 - .../FGMGroundOverlayController.h | 5 +- .../FGMMapEventDelegate.h | 63 ++++++++ .../FLTGoogleMapHeatmapController.h | 1 - .../FLTGoogleMapTileOverlayController.h | 1 + .../GoogleMapCircleController.h | 4 +- .../GoogleMapMarkerController.h | 6 +- .../GoogleMapPolygonController.h | 4 +- .../GoogleMapPolylineController.h | 4 +- 24 files changed, 351 insertions(+), 102 deletions(-) create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.m create mode 100644 packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj index 75ee7f770c3c..0caf990b9847 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 2A6906C72D263DF4001F8426 /* GoogleMapsGroundOverlayControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A6906C62D263DE7001F8426 /* GoogleMapsGroundOverlayControllerTests.m */; }; 2BDE99378062AE3E60B40021 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3ACE0AFE8D82CD5962486AFD /* Pods_RunnerTests.framework */; }; 330909FF2D99B7A60077A751 /* GoogleMapsMarkerControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 330909FE2D99B79B0077A751 /* GoogleMapsMarkerControllerTests.m */; }; + 3378E6352F23F9300045E7DA /* TestMapEventHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 3378E6342F23F92E0045E7DA /* TestMapEventHandler.m */; }; 339355BA2EB3E50300EBF864 /* GoogleMapsCircleControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 339355B92EB3E4F900EBF864 /* GoogleMapsCircleControllerTests.m */; }; 339355BD2EB3E56300EBF864 /* GoogleMapsTileOverlayControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 339355BC2EB3E55600EBF864 /* GoogleMapsTileOverlayControllerTests.m */; }; 339355BF2EB535A600EBF864 /* FLTGoogleMapHeatmapControllerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 339355BE2EB5359B00EBF864 /* FLTGoogleMapHeatmapControllerTests.m */; }; @@ -69,6 +70,8 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 2A6906C62D263DE7001F8426 /* GoogleMapsGroundOverlayControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsGroundOverlayControllerTests.m; sourceTree = ""; }; 330909FE2D99B79B0077A751 /* GoogleMapsMarkerControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsMarkerControllerTests.m; sourceTree = ""; }; + 3378E6332F23F9220045E7DA /* TestMapEventHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestMapEventHandler.h; sourceTree = ""; }; + 3378E6342F23F92E0045E7DA /* TestMapEventHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestMapEventHandler.m; sourceTree = ""; }; 339355B82EB3E4D500EBF864 /* GoogleMapsPolygonControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsPolygonControllerTests.m; sourceTree = ""; }; 339355B92EB3E4F900EBF864 /* GoogleMapsCircleControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsCircleControllerTests.m; sourceTree = ""; }; 339355BC2EB3E55600EBF864 /* GoogleMapsTileOverlayControllerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GoogleMapsTileOverlayControllerTests.m; sourceTree = ""; }; @@ -85,6 +88,7 @@ 61A9A8623F5CA9BBC813DC6B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6851F3552835BC180032B7C8 /* FGMConversionsUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FGMConversionsUtilsTests.m; sourceTree = ""; }; 733AFAB37683A9DA7512F09C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; @@ -148,6 +152,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 784666492D4C4C64000A1A5F /* FlutterFramework */, 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, @@ -226,6 +231,8 @@ 982F2A6B27BADE17003C81F4 /* PartiallyMockedMapView.m */, 33BF9C6C2F2182CB0005FA15 /* TestAssetProvider.h */, 33BF9C6D2F2182DB0005FA15 /* TestAssetProvider.m */, + 3378E6332F23F9220045E7DA /* TestMapEventHandler.h */, + 3378E6342F23F92E0045E7DA /* TestMapEventHandler.m */, F7151F14265D7ED70028CB91 /* Info.plist */, ); path = RunnerTests; @@ -517,6 +524,7 @@ 33BF9C6E2F2182DF0005FA15 /* TestAssetProvider.m in Sources */, 6851F3562835BC180032B7C8 /* FGMConversionsUtilsTests.m in Sources */, 982F2A6C27BADE17003C81F4 /* PartiallyMockedMapView.m in Sources */, + 3378E6352F23F9300045E7DA /* TestMapEventHandler.m in Sources */, 330909FF2D99B7A60077A751 /* GoogleMapsMarkerControllerTests.m in Sources */, 478116522BEF8F47002F593E /* GoogleMapsPolylineControllerTests.m in Sources */, 2A6906C72D263DF4001F8426 /* GoogleMapsGroundOverlayControllerTests.m in Sources */, diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m index fc54f52581f9..049855b05e4d 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMClusterManagersControllerTests.m @@ -7,10 +7,9 @@ @import XCTest; @import GoogleMaps; -#import - #import "PartiallyMockedMapView.h" #import "TestAssetProvider.h" +#import "TestMapEventHandler.h" @interface FGMClusterManagersControllerTests : XCTestCase @end @@ -25,15 +24,14 @@ - (void)testClustering { mapViewOptions.camera = [[GMSCameraPosition alloc] initWithLatitude:0 longitude:0 zoom:0]; PartiallyMockedMapView *mapView = [[PartiallyMockedMapView alloc] initWithOptions:mapViewOptions]; - - id handler = OCMClassMock([FGMMapsCallbackApi class]); + TestMapEventHandler *eventHandler = [[TestMapEventHandler alloc] init]; FGMClusterManagersController *clusterManagersController = - [[FGMClusterManagersController alloc] initWithMapView:mapView callbackHandler:handler]; + [[FGMClusterManagersController alloc] initWithMapView:mapView eventDelegate:eventHandler]; FLTMarkersController *markersController = [[FLTMarkersController alloc] initWithMapView:mapView - callbackHandler:handler + eventDelegate:eventHandler clusterManagersController:clusterManagersController assetProvider:[[TestAssetProvider alloc] init]]; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m index 482089df161e..5277c81395f2 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/FGMConversionsUtilsTests.m @@ -214,7 +214,7 @@ - (void)testCameraUpdateFromNewLatLong { FGMPlatformCameraUpdateNewLatLng *platformUpdate = [FGMPlatformCameraUpdateNewLatLng makeWithLatLng:[FGMPlatformLatLng makeWithLatitude:lat longitude:lng]]; - GMSCameraUpdate *update = FGMGetCameraUpdateForPigeonCameraUpdate( + FGMGetCameraUpdateForPigeonCameraUpdate( [FGMPlatformCameraUpdate makeWithCameraUpdate:platformUpdate]); // GMSCameraUpdate is not inspectable, so this test just ensures that the codepath // doesn't throw. FGMGetCameraUpdateForPigeonCameraUpdate is simple enough that diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m index 2d1a0ef75ce0..a34b11ae3cc0 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsMarkerControllerTests.m @@ -8,6 +8,7 @@ #import "PartiallyMockedMapView.h" #import "TestAssetProvider.h" +#import "TestMapEventHandler.h" /// A GMSMarker that ensures that property updates are made before the map is set. @interface PropertyOrderValidatingMarker : GMSMarker { @@ -31,9 +32,11 @@ + (GMSMapView *)mapView { /// Returns a FLTMarkersController instance instantiated with the given map view. /// /// The mapView should outlive the controller, as the controller keeps a weak reference to it. -- (FLTMarkersController *)markersControllerWithMapView:(GMSMapView *)mapView { +- (FLTMarkersController *)markersControllerWithMapView:(GMSMapView *)mapView + eventDelegate: + (NSObject *)eventDelegate { return [[FLTMarkersController alloc] initWithMapView:mapView - callbackHandler:[[FGMMapsCallbackApi alloc] init] + eventDelegate:eventDelegate clusterManagersController:nil assetProvider:[[TestAssetProvider alloc] init]]; } @@ -44,7 +47,9 @@ - (FGMPlatformBitmap *)placeholderBitmap { - (void)testSetsMarkerNumericProperties { GMSMapView *mapView = [GoogleMapsMarkerControllerTests mapView]; - FLTMarkersController *controller = [self markersControllerWithMapView:mapView]; + TestMapEventHandler *eventHandler = [[TestMapEventHandler alloc] init]; + FLTMarkersController *controller = [self markersControllerWithMapView:mapView + eventDelegate:eventHandler]; NSString *markerIdentifier = @"marker"; double anchorX = 3.14; @@ -91,7 +96,9 @@ - (void)testSetsMarkerNumericProperties { // another property. - (void)testSetsDraggable { GMSMapView *mapView = [GoogleMapsMarkerControllerTests mapView]; - FLTMarkersController *controller = [self markersControllerWithMapView:mapView]; + TestMapEventHandler *eventHandler = [[TestMapEventHandler alloc] init]; + FLTMarkersController *controller = [self markersControllerWithMapView:mapView + eventDelegate:eventHandler]; NSString *markerIdentifier = @"marker"; [controller addMarkers:@[ [FGMPlatformMarker @@ -123,7 +130,9 @@ - (void)testSetsDraggable { // another property. - (void)testSetsFlat { GMSMapView *mapView = [GoogleMapsMarkerControllerTests mapView]; - FLTMarkersController *controller = [self markersControllerWithMapView:mapView]; + TestMapEventHandler *eventHandler = [[TestMapEventHandler alloc] init]; + FLTMarkersController *controller = [self markersControllerWithMapView:mapView + eventDelegate:eventHandler]; NSString *markerIdentifier = @"marker"; [controller addMarkers:@[ [FGMPlatformMarker @@ -155,7 +164,9 @@ - (void)testSetsFlat { // another property. - (void)testSetsVisible { GMSMapView *mapView = [GoogleMapsMarkerControllerTests mapView]; - FLTMarkersController *controller = [self markersControllerWithMapView:mapView]; + TestMapEventHandler *eventHandler = [[TestMapEventHandler alloc] init]; + FLTMarkersController *controller = [self markersControllerWithMapView:mapView + eventDelegate:eventHandler]; NSString *markerIdentifier = @"marker"; [controller addMarkers:@[ [FGMPlatformMarker @@ -186,7 +197,9 @@ - (void)testSetsVisible { - (void)testSetsMarkerInfoWindowProperties { GMSMapView *mapView = [GoogleMapsMarkerControllerTests mapView]; - FLTMarkersController *controller = [self markersControllerWithMapView:mapView]; + TestMapEventHandler *eventHandler = [[TestMapEventHandler alloc] init]; + FLTMarkersController *controller = [self markersControllerWithMapView:mapView + eventDelegate:eventHandler]; NSString *markerIdentifier = @"marker"; NSString *title = @"info title"; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h index 165ba0b0dc5b..dbe80f9a2ef5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestAssetProvider.h @@ -5,7 +5,9 @@ @import Foundation; @import google_maps_flutter_ios; -/// Fake implementation of FGMAssetProvider. +NS_ASSUME_NONNULL_BEGIN + +/// Fake implementation of FGMAssetProvider for unit tests. @interface TestAssetProvider : NSObject /// Initializes an instance that returns an arbitrary key for the given asset /// name, and the given image when when using that key for imageNamed:. @@ -18,3 +20,5 @@ forAssetName:(NSString *)assetName package:(nullable NSString *)package; @end + +NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h new file mode 100644 index 000000000000..a8bd18cc9318 --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h @@ -0,0 +1,14 @@ +// 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 Foundation; +@import google_maps_flutter_ios; + +NS_ASSUME_NONNULL_BEGIN + +/// Fake implementation of FGMAssetProvider for unit tests. +@interface TestMapEventHandler : NSObject +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.m new file mode 100644 index 000000000000..190d1b1af4fc --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.m @@ -0,0 +1,56 @@ +// 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 "TestMapEventHandler.h" + +@implementation TestMapEventHandler + +- (void)didStartCameraMove { +} + +- (void)didMoveCameraToPosition:(FGMPlatformCameraPosition *)cameraPosition { +} + +- (void)didIdleCamera { +} + +- (void)didTapAtPosition:(FGMPlatformLatLng *)position { +} + +- (void)didLongPressAtPosition:(FGMPlatformLatLng *)position { +} + +- (void)didTapMarkerWithIdentifier:(NSString *)markerId { +} + +- (void)didStartDragForMarkerWithIdentifier:(NSString *)markerId + atPosition:(FGMPlatformLatLng *)position { +} + +- (void)didDragMarkerWithIdentifier:(NSString *)markerId atPosition:(FGMPlatformLatLng *)position { +} + +- (void)didEndDragForMarkerWithIdentifier:(NSString *)markerId + atPosition:(FGMPlatformLatLng *)position { +} + +- (void)didTapInfoWindowOfMarkerWithIdentifier:(NSString *)markerId { +} + +- (void)didTapCircleWithIdentifier:(NSString *)circleId { +} + +- (void)didTapCluster:(FGMPlatformCluster *)cluster { +} + +- (void)didTapPolygonWithIdentifier:(NSString *)polygonId { +} + +- (void)didTapPolylineWithIdentifier:(NSString *)polylineId { +} + +- (void)didTapGroundOverlayWithIdentifier:(NSString *)groundOverlayId { +} + +@end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMClusterManagersController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMClusterManagersController.m index 04c3f04c9285..ee8ddc806f13 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMClusterManagersController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMClusterManagersController.m @@ -13,8 +13,8 @@ @interface FGMClusterManagersController () @property(strong, nonatomic) NSMutableDictionary *clusterManagerIdentifierToManagers; -/// The callback handler interface for calls to Flutter. -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +/// The delegate for handling interactions with clusters. +@property(weak, nonatomic) NSObject *eventDelegate; /// The current map instance on which the cluster managers are operating. @property(strong, nonatomic) GMSMapView *mapView; @@ -23,10 +23,10 @@ @interface FGMClusterManagersController () @implementation FGMClusterManagersController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler { + eventDelegate:(NSObject *)eventDelegate { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _eventDelegate = eventDelegate; _mapView = mapView; _clusterManagerIdentifierToManagers = [[NSMutableDictionary alloc] init]; } @@ -106,9 +106,7 @@ - (void)didTapCluster:(GMUStaticCluster *)cluster { return; } FGMPlatformCluster *platFormCluster = FGMGetPigeonCluster(cluster, clusterManagerId); - [self.callbackHandler didTapCluster:platFormCluster - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapCluster:platFormCluster]; } #pragma mark - Private methods diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m index d83a14f53a32..f1fe7281dc09 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/FGMGroundOverlayController.m @@ -86,7 +86,7 @@ @interface FLTGroundOverlaysController () *groundOverlayControllerByIdentifier; /// A callback api for the map interactions. -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(weak, nonatomic) NSObject *eventDelegate; /// Asset provider used to load images. @property(weak, nonatomic) NSObject *assetProvider; @@ -99,11 +99,11 @@ @interface FLTGroundOverlaysController () @implementation FLTGroundOverlaysController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler + eventDelegate:(NSObject *)eventDelegate assetProvider:(NSObject *)assetProvider { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _eventDelegate = eventDelegate; _mapView = mapView; _groundOverlayControllerByIdentifier = [[NSMutableDictionary alloc] init]; _assetProvider = assetProvider; @@ -180,9 +180,7 @@ - (void)didTapGroundOverlayWithIdentifier:(NSString *)identifier { if (!controller) { return; } - [self.callbackHandler didTapGroundOverlayWithIdentifier:identifier - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapGroundOverlayWithIdentifier:identifier]; } - (bool)hasGroundOverlaysWithIdentifier:(NSString *)identifier { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m index 6fe3518e55af..1348601ce0ff 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapCircleController.m @@ -60,7 +60,7 @@ + (void)updateCircle:(GMSCircle *)circle @interface FLTCirclesController () -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(weak, nonatomic) NSObject *eventDelegate; @property(weak, nonatomic) GMSMapView *mapView; @property(strong, nonatomic) NSMutableDictionary *circleIdToController; @@ -69,10 +69,10 @@ @interface FLTCirclesController () @implementation FLTCirclesController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler { + eventDelegate:(NSObject *)eventDelegate { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _eventDelegate = eventDelegate; _mapView = mapView; _circleIdToController = [NSMutableDictionary dictionaryWithCapacity:1]; } @@ -121,9 +121,7 @@ - (void)didTapCircleWithIdentifier:(NSString *)identifier { if (!controller) { return; } - [self.callbackHandler didTapCircleWithIdentifier:identifier - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapCircleWithIdentifier:identifier]; } @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m index 9e84b1285016..dbb6c6f9105c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m @@ -101,6 +101,121 @@ - (UIImage *)imageNamed:(NSString *)name { #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 FLTGoogleMapController *)controller @@ -134,6 +249,7 @@ @interface FLTGoogleMapController () @property(nonatomic, strong) GMSMapView *mapView; @property(nonatomic, strong) FGMMapsCallbackApi *dartCallbackHandler; +@property(nonatomic, strong) FGMDefaultMapEventHandler *mapEventHandler; @property(nonatomic, assign) BOOL trackCameraPosition; @property(nonatomic, weak) NSObject *registrar; @property(nonatomic, strong) FGMClusterManagersController *clusterManagersController; @@ -197,6 +313,8 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:registrar.messenger messageChannelSuffix:pigeonSuffix]; + _mapEventHandler = + [[FGMDefaultMapEventHandler alloc] initWithCallbackHandler:_dartCallbackHandler]; _mapView.delegate = self; _mapView.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; _registrar = registrar; @@ -204,23 +322,23 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView [[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar]; _clusterManagersController = [[FGMClusterManagersController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler]; + eventDelegate:_mapEventHandler]; _markersController = [[FLTMarkersController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler + eventDelegate:_mapEventHandler clusterManagersController:_clusterManagersController assetProvider:assetProvider]; _polygonsController = [[FLTPolygonsController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler]; + eventDelegate:_mapEventHandler]; _polylinesController = [[FLTPolylinesController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler]; + eventDelegate:_mapEventHandler]; _circlesController = [[FLTCirclesController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler]; + eventDelegate:_mapEventHandler]; _heatmapsController = [[FLTHeatmapsController alloc] initWithMapView:_mapView]; _tileOverlaysController = [[FLTTileOverlaysController alloc] initWithMapView:_mapView tileProvider:self]; _groundOverlaysController = [[FLTGroundOverlaysController alloc] initWithMapView:_mapView - callbackHandler:_dartCallbackHandler + eventDelegate:_mapEventHandler assetProvider:assetProvider]; [_clusterManagersController addClusterManagers:creationParameters.initialClusterManagers]; [_markersController addMarkers:creationParameters.initialMarkers]; @@ -384,22 +502,17 @@ - (NSString *)setMapStyle:(NSString *)mapStyle { #pragma mark - GMSMapViewDelegate methods - (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture { - [self.dartCallbackHandler didStartCameraMoveWithCompletion:^(FlutterError *_Nullable _){ - }]; + [self.mapEventHandler didStartCameraMove]; } - (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position { if (self.trackCameraPosition) { - [self.dartCallbackHandler - didMoveCameraToPosition:FGMGetPigeonCameraPositionForPosition(position) - completion:^(FlutterError *_Nullable _){ - }]; + [self.mapEventHandler didMoveCameraToPosition:FGMGetPigeonCameraPositionForPosition(position)]; } } - (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position { - [self.dartCallbackHandler didIdleCameraWithCompletion:^(FlutterError *_Nullable _){ - }]; + [self.mapEventHandler didIdleCamera]; } - (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { @@ -448,15 +561,11 @@ - (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay { } - (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.dartCallbackHandler didTapAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate) - completion:^(FlutterError *_Nullable _){ - }]; + [self.mapEventHandler didTapAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; } - (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate { - [self.dartCallbackHandler didLongPressAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate) - completion:^(FlutterError *_Nullable _){ - }]; + [self.mapEventHandler didLongPressAtPosition:FGMGetPigeonLatLngForCoordinate(coordinate)]; } - (void)interpretMapConfiguration:(FGMPlatformMapConfiguration *)config { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m index 7b9e5543238b..9d061eec8b09 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapMarkerController.m @@ -108,8 +108,9 @@ + (void)updateMarker:(GMSMarker *)marker @interface FLTMarkersController () -@property(strong, nonatomic, readwrite) NSMutableDictionary *markerIdentifierToController; -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(strong, nonatomic, readwrite) + NSMutableDictionary *markerIdentifierToController; +@property(weak, nonatomic) NSObject *eventDelegate; /// Controller for adding/removing/fetching cluster managers @property(weak, nonatomic, nullable) FGMClusterManagersController *clusterManagersController; @property(weak, nonatomic) NSObject *assetProvider; @@ -120,12 +121,12 @@ @interface FLTMarkersController () @implementation FLTMarkersController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler + eventDelegate:(NSObject *)eventDelegate clusterManagersController:(nullable FGMClusterManagersController *)clusterManagersController assetProvider:(NSObject *)assetProvider { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _eventDelegate = eventDelegate; _mapView = mapView; _clusterManagersController = clusterManagersController; _markerIdentifierToController = [[NSMutableDictionary alloc] init]; @@ -232,9 +233,7 @@ - (BOOL)didTapMarkerWithIdentifier:(NSString *)identifier { if (!controller) { return NO; } - [self.callbackHandler didTapMarkerWithIdentifier:identifier - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapMarkerWithIdentifier:identifier]; return controller.consumeTapEvents; } @@ -247,11 +246,9 @@ - (void)didStartDraggingMarkerWithIdentifier:(NSString *)identifier if (!controller) { return; } - [self.callbackHandler + [self.eventDelegate didStartDragForMarkerWithIdentifier:identifier - atPosition:FGMGetPigeonLatLngForCoordinate(location) - completion:^(FlutterError *_Nullable _){ - }]; + atPosition:FGMGetPigeonLatLngForCoordinate(location)]; } - (void)didDragMarkerWithIdentifier:(NSString *)identifier @@ -263,10 +260,8 @@ - (void)didDragMarkerWithIdentifier:(NSString *)identifier if (!controller) { return; } - [self.callbackHandler didDragMarkerWithIdentifier:identifier - atPosition:FGMGetPigeonLatLngForCoordinate(location) - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didDragMarkerWithIdentifier:identifier + atPosition:FGMGetPigeonLatLngForCoordinate(location)]; } - (void)didEndDraggingMarkerWithIdentifier:(NSString *)identifier @@ -275,17 +270,13 @@ - (void)didEndDraggingMarkerWithIdentifier:(NSString *)identifier if (!controller) { return; } - [self.callbackHandler didEndDragForMarkerWithIdentifier:identifier - atPosition:FGMGetPigeonLatLngForCoordinate(location) - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didEndDragForMarkerWithIdentifier:identifier + atPosition:FGMGetPigeonLatLngForCoordinate(location)]; } - (void)didTapInfoWindowOfMarkerWithIdentifier:(NSString *)identifier { if (identifier && self.markerIdentifierToController[identifier]) { - [self.callbackHandler didTapInfoWindowOfMarkerWithIdentifier:identifier - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapInfoWindowOfMarkerWithIdentifier:identifier]; } } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m index 469d61aa1859..f5d077bd4ff1 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolygonController.m @@ -70,7 +70,7 @@ + (void)updatePolygon:(GMSPolygon *)polygon @interface FLTPolygonsController () @property(strong, nonatomic) NSMutableDictionary *polygonIdentifierToController; -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(weak, nonatomic) NSObject *eventDelegate; @property(weak, nonatomic) GMSMapView *mapView; @end @@ -78,10 +78,10 @@ @interface FLTPolygonsController () @implementation FLTPolygonsController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler { + eventDelegate:(NSObject *)eventDelegate { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _eventDelegate = eventDelegate; _mapView = mapView; _polygonIdentifierToController = [NSMutableDictionary dictionaryWithCapacity:1]; } @@ -128,9 +128,7 @@ - (void)didTapPolygonWithIdentifier:(NSString *)identifier { if (!controller) { return; } - [self.callbackHandler didTapPolygonWithIdentifier:identifier - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapPolygonWithIdentifier:identifier]; } - (bool)hasPolygonWithIdentifier:(NSString *)identifier { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m index 4c7923f8cd7d..ea84a4e5be54 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapPolylineController.m @@ -63,7 +63,7 @@ + (void)updatePolyline:(GMSPolyline *)polyline @interface FLTPolylinesController () @property(strong, nonatomic) NSMutableDictionary *polylineIdentifierToController; -@property(strong, nonatomic) FGMMapsCallbackApi *callbackHandler; +@property(weak, nonatomic) NSObject *eventDelegate; @property(weak, nonatomic) GMSMapView *mapView; @end @@ -72,10 +72,10 @@ @interface FLTPolylinesController () @implementation FLTPolylinesController - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler { + eventDelegate:(NSObject *)eventDelegate { self = [super init]; if (self) { - _callbackHandler = callbackHandler; + _eventDelegate = eventDelegate; _mapView = mapView; _polylineIdentifierToController = [NSMutableDictionary dictionaryWithCapacity:1]; } @@ -122,9 +122,7 @@ - (void)didTapPolylineWithIdentifier:(NSString *)identifier { if (!controller) { return; } - [self.callbackHandler didTapPolylineWithIdentifier:identifier - completion:^(FlutterError *_Nullable _){ - }]; + [self.eventDelegate didTapPolylineWithIdentifier:identifier]; } - (bool)hasPolylineWithIdentifier:(NSString *)identifier { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMClusterManagersController.h index 98afbb34d1f0..b6134c6b9d28 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMClusterManagersController.h @@ -6,6 +6,7 @@ @import GoogleMaps; @import GoogleMapsUtils; +#import "FGMMapEventDelegate.h" #import "google_maps_flutter_pigeon_messages.g.h" NS_ASSUME_NONNULL_BEGIN @@ -15,10 +16,10 @@ NS_ASSUME_NONNULL_BEGIN /// Initializes cluster manager controller. /// -/// @param callbackHandler A callback handler. +/// @param eventDelegate A delegate that will receive events from the cluster managers. /// @param mapView A map view that will be used to display clustered markers. - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler; + eventDelegate:(NSObject *)eventDelegate; /// Creates cluster managers and initializes them. /// diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMConversionUtils.h index c7821882297c..788c585c6f34 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMConversionUtils.h @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@import Flutter; @import Foundation; @import GoogleMaps; @import GoogleMapsUtils; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController.h index 398feb2c6cbc..f4a07aa950e5 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMGroundOverlayController.h @@ -8,6 +8,7 @@ @import UIKit; #import "FGMAssetProvider.h" +#import "FGMMapEventDelegate.h" #import "google_maps_flutter_pigeon_messages.g.h" NS_ASSUME_NONNULL_BEGIN @@ -37,9 +38,9 @@ NS_ASSUME_NONNULL_BEGIN /// Controller of multiple ground overlays on the map. @interface FLTGroundOverlaysController : NSObject -/// Initializes the controller with a GMSMapView, callback handler and asset provider. +/// Initializes the controller with a GMSMapView, event delegate, and asset provider. - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler + eventDelegate:(NSObject *)eventDelegate assetProvider:(NSObject *)assetProvider; /// Adds ground overlays to the map. diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h new file mode 100644 index 000000000000..874115c0c33e --- /dev/null +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h @@ -0,0 +1,63 @@ +// 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 Foundation; + +#import "google_maps_flutter_pigeon_messages.g.h" + +NS_ASSUME_NONNULL_BEGIN + +/// Delegate for map event notifications. +@protocol FGMMapEventDelegate + +/// Called when the map camera starts moving. +- (void)didStartCameraMove; + +/// Called when the map camera moves. +- (void)didMoveCameraToPosition:(FGMPlatformCameraPosition *)cameraPosition; + +/// Called when the map camera stops moving. +- (void)didIdleCamera; + +/// Called when the map, not a specifc map object, is tapped. +- (void)didTapAtPosition:(FGMPlatformLatLng *)position; + +/// Called when the map, not a specifc map object, is long pressed. +- (void)didLongPressAtPosition:(FGMPlatformLatLng *)position; + +/// Called when a marker is tapped. +- (void)didTapMarkerWithIdentifier:(NSString *)markerId; + +/// Called when a marker drag starts. +- (void)didStartDragForMarkerWithIdentifier:(NSString *)markerId + atPosition:(FGMPlatformLatLng *)position; + +/// Called when a marker drag updates. +- (void)didDragMarkerWithIdentifier:(NSString *)markerId atPosition:(FGMPlatformLatLng *)position; + +/// Called when a marker drag ends. +- (void)didEndDragForMarkerWithIdentifier:(NSString *)markerId + atPosition:(FGMPlatformLatLng *)position; + +/// Called when a marker's info window is tapped. +- (void)didTapInfoWindowOfMarkerWithIdentifier:(NSString *)markerId; + +/// Called when a circle is tapped. +- (void)didTapCircleWithIdentifier:(NSString *)circleId; + +/// Called when a marker cluster is tapped. +- (void)didTapCluster:(FGMPlatformCluster *)cluster; + +/// Called when a polygon is tapped. +- (void)didTapPolygonWithIdentifier:(NSString *)polygonId; + +/// Called when a polyline is tapped. +- (void)didTapPolylineWithIdentifier:(NSString *)polylineId; + +/// Called when a ground overlay is tapped. +- (void)didTapGroundOverlayWithIdentifier:(NSString *)groundOverlayId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapHeatmapController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapHeatmapController.h index edba379ac0e3..93c2aacf5e57 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapHeatmapController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapHeatmapController.h @@ -2,7 +2,6 @@ // 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; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h index 20417e07b74a..b4c707e6d0b4 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FLTGoogleMapTileOverlayController.h @@ -2,6 +2,7 @@ // 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 "google_maps_flutter_pigeon_messages.g.h" diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h index 9ba10f7dacb4..ac4347551135 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapCircleController.h @@ -2,9 +2,9 @@ // 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 "FGMMapEventDelegate.h" #import "google_maps_flutter_pigeon_messages.g.h" NS_ASSUME_NONNULL_BEGIN @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTCirclesController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler; + eventDelegate:(NSObject *)eventDelegate; - (void)addCircles:(NSArray *)circlesToAdd; - (void)changeCircles:(NSArray *)circlesToChange; - (void)removeCirclesWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h index 5222c558fde1..57797346639e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapMarkerController.h @@ -7,11 +7,13 @@ #import "FGMAssetProvider.h" #import "FGMClusterManagersController.h" -#import "GoogleMapController.h" +#import "FGMMapEventDelegate.h" #import "google_maps_flutter_pigeon_messages.g.h" NS_ASSUME_NONNULL_BEGIN +#pragma mark - + // Defines marker controllable by Flutter. @interface FLTGoogleMapMarkerController : NSObject @property(assign, nonatomic, readonly) BOOL consumeTapEvents; @@ -26,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FLTMarkersController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler + eventDelegate:(NSObject *)eventDelegate clusterManagersController:(nullable FGMClusterManagersController *)clusterManagersController assetProvider:(NSObject *)assetProvider; - (void)addMarkers:(NSArray *)markersToAdd; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h index bd2e78fd9627..a222ca6a4eb0 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolygonController.h @@ -2,9 +2,9 @@ // 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 "FGMMapEventDelegate.h" #import "google_maps_flutter_pigeon_messages.g.h" // Defines polygon controllable by Flutter. @@ -17,7 +17,7 @@ @interface FLTPolygonsController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler; + eventDelegate:(NSObject *)eventDelegate; - (void)addPolygons:(NSArray *)polygonsToAdd; - (void)changePolygons:(NSArray *)polygonsToChange; - (void)removePolygonWithIdentifiers:(NSArray *)identifiers; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h index b500c86975f5..ccf37dae9a35 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapPolylineController.h @@ -2,9 +2,9 @@ // 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 "FGMMapEventDelegate.h" #import "google_maps_flutter_pigeon_messages.g.h" // Defines polyline controllable by Flutter. @@ -17,7 +17,7 @@ @interface FLTPolylinesController : NSObject - (instancetype)initWithMapView:(GMSMapView *)mapView - callbackHandler:(FGMMapsCallbackApi *)callbackHandler; + eventDelegate:(NSObject *)eventDelegate; - (void)addPolylines:(NSArray *)polylinesToAdd; - (void)changePolylines:(NSArray *)polylinesToChange; - (void)removePolylineWithIdentifiers:(NSArray *)identifiers; From 9cbd64a19aa4f9f3e5f9ba18d0dc380061e9c225 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 23 Jan 2026 14:16:16 -0500 Subject: [PATCH 06/11] Switch mocks to simple test objects --- .../example/ios/RunnerTests/GoogleMapsTests.m | 46 ++++++++++++------- .../ios/RunnerTests/PartiallyMockedMapView.h | 11 ++--- .../ios/RunnerTests/PartiallyMockedMapView.m | 5 ++ 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m index 98249a978710..e6c6edf4ff05 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m @@ -9,6 +9,26 @@ #import #import "PartiallyMockedMapView.h" +@interface MockCATransaction : NSObject +@property(nonatomic, assign) BOOL beginCalled; +@property(nonatomic, assign) BOOL commitCalled; +@property(nonatomic, assign) CFTimeInterval animationDuration; +@end + +@implementation MockCATransaction + +- (void)begin { + self.beginCalled = YES; +} + +- (void)commit { + self.commitCalled = YES; +} + +@end + +#pragma mark - + @interface FLTGoogleMapFactory (Test) @property(strong, nonatomic, readonly) id sharedMapServices; @end @@ -99,20 +119,17 @@ - (void)testAnimateCameraWithUpdate { creationParameters:[self emptyCreationParameters] registrar:registrar]; - id mapViewMock = OCMPartialMock(mapView); - id mockTransactionWrapper = OCMProtocolMock(@protocol(FGMCATransactionProtocol)); + MockCATransaction *mockTransactionWrapper = [[MockCATransaction alloc] init]; controller.callHandler.transactionWrapper = mockTransactionWrapper; FGMPlatformCameraUpdateZoomTo *zoomTo = [FGMPlatformCameraUpdateZoomTo makeWithZoom:10.0]; FGMPlatformCameraUpdate *cameraUpdate = [FGMPlatformCameraUpdate makeWithCameraUpdate:zoomTo]; FlutterError *error = nil; - OCMReject([mockTransactionWrapper begin]); - OCMReject([mockTransactionWrapper commit]); - OCMExpect([mapViewMock animateWithCameraUpdate:[OCMArg any]]); [controller.callHandler animateCameraWithUpdate:cameraUpdate duration:nil error:&error]; - OCMVerifyAll(mapViewMock); - OCMVerifyAll(mockTransactionWrapper); + XCTAssertTrue(mapView.didAnimateCamera); + XCTAssertFalse(mockTransactionWrapper.beginCalled); + XCTAssertFalse(mockTransactionWrapper.commitCalled); } - (void)testAnimateCameraWithUpdateAndDuration { @@ -133,8 +150,7 @@ - (void)testAnimateCameraWithUpdateAndDuration { creationParameters:[self emptyCreationParameters] registrar:registrar]; - id mapViewMock = OCMPartialMock(mapView); - id mockTransactionWrapper = OCMProtocolMock(@protocol(FGMCATransactionProtocol)); + MockCATransaction *mockTransactionWrapper = [[MockCATransaction alloc] init]; controller.callHandler.transactionWrapper = mockTransactionWrapper; FGMPlatformCameraUpdateZoomTo *zoomTo = [FGMPlatformCameraUpdateZoomTo makeWithZoom:10.0]; @@ -142,16 +158,14 @@ - (void)testAnimateCameraWithUpdateAndDuration { FlutterError *error = nil; NSNumber *durationMilliseconds = @100; - OCMExpect([mockTransactionWrapper begin]); - OCMExpect( - [mockTransactionWrapper setAnimationDuration:[durationMilliseconds doubleValue] / 1000]); - OCMExpect([mockTransactionWrapper commit]); - OCMExpect([mapViewMock animateWithCameraUpdate:[OCMArg any]]); [controller.callHandler animateCameraWithUpdate:cameraUpdate duration:durationMilliseconds error:&error]; - OCMVerifyAll(mapViewMock); - OCMVerifyAll(mockTransactionWrapper); + XCTAssertTrue(mapView.didAnimateCamera); + XCTAssertTrue(mockTransactionWrapper.beginCalled); + XCTAssertTrue(mockTransactionWrapper.commitCalled); + XCTAssertEqual(mockTransactionWrapper.animationDuration, + [durationMilliseconds doubleValue] / 1000); } - (void)testInspectorAPICameraPosition { diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.h b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.h index 9a04ae84ab24..7b4665cb6820 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.h @@ -4,14 +4,13 @@ @import GoogleMaps; -/** - * Defines a map view used for testing key-value observing. - */ +/// Defines a map view used for testing key-value observing. @interface PartiallyMockedMapView : GMSMapView -/** - * The number of times that the `frame` KVO has been added. - */ +/// The number of times that the `frame` KVO has been added. @property(nonatomic, assign, readonly) NSInteger frameObserverCount; +/// True if animateWithCameraUpdate: was called. +@property(nonatomic, assign) BOOL didAnimateCamera; + @end diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.m index 47d48d2e07fc..84b02710180b 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/PartiallyMockedMapView.m @@ -31,4 +31,9 @@ - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath { } } +- (void)animateWithCameraUpdate:(GMSCameraUpdate *)cameraUpdate { + [super animateWithCameraUpdate:cameraUpdate]; + self.didAnimateCamera = YES; +} + @end From b25f78a3d3f5aa58e16087f843707d1a7f9696b4 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 23 Jan 2026 15:15:29 -0500 Subject: [PATCH 07/11] Remove the remaining OCMock usage --- .../example/ios/RunnerTests/GoogleMapsTests.m | 49 +++++++++++++------ .../GoogleMapController.m | 22 ++++----- .../GoogleMapController_Test.h | 7 ++- 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m index e6c6edf4ff05..e51da47062f7 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/GoogleMapsTests.m @@ -6,8 +6,8 @@ @import XCTest; @import GoogleMaps; -#import #import "PartiallyMockedMapView.h" +#import "TestAssetProvider.h" @interface MockCATransaction : NSObject @property(nonatomic, assign) BOOL beginCalled; @@ -27,6 +27,27 @@ - (void)commit { @end +// No-op implementation of FlutterBinaryMessenger. +@interface StubBinaryMessenger : NSObject +@end + +@implementation StubBinaryMessenger +- (void)sendOnChannel:(NSString *)channel message:(NSData *)message { +} +- (void)sendOnChannel:(NSString *)channel + message:(NSData *)message + binaryReply:(FlutterBinaryReply)reply { +} +- (void)cleanUpConnection:(FlutterBinaryMessengerConnection)connection { +} +- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString *)channel + binaryMessageHandler: + (FlutterBinaryMessageHandler _Nullable)handler { + return 0; +} + +@end + #pragma mark - @interface FLTGoogleMapFactory (Test) @@ -48,7 +69,6 @@ - (void)testPlugin { } - (void)testFrameObserver { - id registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); CGRect frame = CGRectMake(0, 0, 100, 100); GMSMapViewOptions *options = [[GMSMapViewOptions alloc] init]; options.frame = frame; @@ -58,7 +78,8 @@ - (void)testFrameObserver { [[FLTGoogleMapController alloc] initWithMapView:mapView viewIdentifier:0 creationParameters:[self emptyCreationParameters] - registrar:registrar]; + assetProvider:[[TestAssetProvider alloc] init] + binaryMessenger:[[StubBinaryMessenger alloc] init]]; for (NSInteger i = 0; i < 10; ++i) { [controller view]; @@ -70,7 +91,9 @@ - (void)testFrameObserver { } - (void)testMapsServiceSync { - id registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); + // 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. + id registrar = [[NSObject alloc] init]; FLTGoogleMapFactory *factory1 = [[FLTGoogleMapFactory alloc] initWithRegistrar:registrar]; XCTAssertNotNil(factory1.sharedMapServices); FLTGoogleMapFactory *factory2 = [[FLTGoogleMapFactory alloc] initWithRegistrar:registrar]; @@ -102,8 +125,6 @@ - (void)testHandleResultTileDownsamplesWideGamutImages { } - (void)testAnimateCameraWithUpdate { - NSObject *registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); - CGRect frame = CGRectMake(0, 0, 100, 100); GMSMapViewOptions *mapViewOptions = [[GMSMapViewOptions alloc] init]; mapViewOptions.frame = frame; @@ -117,7 +138,8 @@ - (void)testAnimateCameraWithUpdate { [[FLTGoogleMapController alloc] initWithMapView:mapView viewIdentifier:0 creationParameters:[self emptyCreationParameters] - registrar:registrar]; + assetProvider:[[TestAssetProvider alloc] init] + binaryMessenger:[[StubBinaryMessenger alloc] init]]; MockCATransaction *mockTransactionWrapper = [[MockCATransaction alloc] init]; controller.callHandler.transactionWrapper = mockTransactionWrapper; @@ -133,8 +155,6 @@ - (void)testAnimateCameraWithUpdate { } - (void)testAnimateCameraWithUpdateAndDuration { - NSObject *registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); - CGRect frame = CGRectMake(0, 0, 100, 100); GMSMapViewOptions *mapViewOptions = [[GMSMapViewOptions alloc] init]; mapViewOptions.frame = frame; @@ -148,7 +168,8 @@ - (void)testAnimateCameraWithUpdateAndDuration { [[FLTGoogleMapController alloc] initWithMapView:mapView viewIdentifier:0 creationParameters:[self emptyCreationParameters] - registrar:registrar]; + assetProvider:[[TestAssetProvider alloc] init] + binaryMessenger:[[StubBinaryMessenger alloc] init]]; MockCATransaction *mockTransactionWrapper = [[MockCATransaction alloc] init]; controller.callHandler.transactionWrapper = mockTransactionWrapper; @@ -169,8 +190,6 @@ - (void)testAnimateCameraWithUpdateAndDuration { } - (void)testInspectorAPICameraPosition { - NSObject *registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); - CGRect frame = CGRectMake(0, 0, 100, 100); GMSMapViewOptions *mapViewOptions = [[GMSMapViewOptions alloc] init]; mapViewOptions.frame = frame; @@ -183,14 +202,16 @@ - (void)testInspectorAPICameraPosition { PartiallyMockedMapView *mapView = [[PartiallyMockedMapView alloc] initWithOptions:mapViewOptions]; + NSObject *binaryMessenger = [[StubBinaryMessenger alloc] init]; FLTGoogleMapController *controller = [[FLTGoogleMapController alloc] initWithMapView:mapView viewIdentifier:0 creationParameters:[self emptyCreationParameters] - registrar:registrar]; + assetProvider:[[TestAssetProvider alloc] init] + binaryMessenger:binaryMessenger]; FGMMapInspector *inspector = [[FGMMapInspector alloc] initWithMapController:controller - messenger:registrar.messenger + messenger:binaryMessenger pigeonSuffix:@"0"]; FlutterError *error = nil; diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m index dbb6c6f9105c..c265785d624e 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/GoogleMapController.m @@ -15,8 +15,6 @@ #import "FLTGoogleMapTileOverlayController.h" #import "google_maps_flutter_pigeon_messages.g.h" -#pragma mark - Conversion of JSON-like values sent via platform channels. Forward declarations. - @interface FLTGoogleMapFactory () @property(weak, nonatomic) NSObject *registrar; @@ -251,7 +249,6 @@ @interface FLTGoogleMapController () @property(nonatomic, strong) FGMMapsCallbackApi *dartCallbackHandler; @property(nonatomic, strong) FGMDefaultMapEventHandler *mapEventHandler; @property(nonatomic, assign) BOOL trackCameraPosition; -@property(nonatomic, weak) NSObject *registrar; @property(nonatomic, strong) FGMClusterManagersController *clusterManagersController; @property(nonatomic, strong) FLTMarkersController *markersController; @property(nonatomic, strong) FLTPolygonsController *polygonsController; @@ -296,13 +293,15 @@ - (instancetype)initWithFrame:(CGRect)frame return [self initWithMapView:mapView viewIdentifier:viewId creationParameters:creationParameters - registrar:registrar]; + assetProvider:[[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar] + binaryMessenger:registrar.messenger]; } - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView viewIdentifier:(int64_t)viewId creationParameters:(FGMPlatformMapViewCreationParams *)creationParameters - registrar:(NSObject *_Nonnull)registrar { + assetProvider:(NSObject *)assetProvider + binaryMessenger:(NSObject *)binaryMessenger { if (self = [super init]) { _mapView = mapView; @@ -311,15 +310,12 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView // https://github.com/flutter/flutter/issues/104121 [self interpretMapConfiguration:creationParameters.mapConfiguration]; NSString *pigeonSuffix = [NSString stringWithFormat:@"%lld", viewId]; - _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:registrar.messenger + _dartCallbackHandler = [[FGMMapsCallbackApi alloc] initWithBinaryMessenger:binaryMessenger messageChannelSuffix:pigeonSuffix]; _mapEventHandler = [[FGMDefaultMapEventHandler alloc] initWithCallbackHandler:_dartCallbackHandler]; _mapView.delegate = self; _mapView.paddingAdjustmentBehavior = kGMSMapViewPaddingAdjustmentBehaviorNever; - _registrar = registrar; - FGMDefaultAssetProvider *assetProvider = - [[FGMDefaultAssetProvider alloc] initWithRegistrar:registrar]; _clusterManagersController = [[FGMClusterManagersController alloc] initWithMapView:_mapView eventDelegate:_mapEventHandler]; @@ -355,13 +351,13 @@ - (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView [_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil]; _callHandler = [[FGMMapCallHandler alloc] initWithMapController:self - messenger:registrar.messenger + messenger:binaryMessenger pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsApiWithSuffix(registrar.messenger, _callHandler, pigeonSuffix); + SetUpFGMMapsApiWithSuffix(binaryMessenger, _callHandler, pigeonSuffix); _inspector = [[FGMMapInspector alloc] initWithMapController:self - messenger:registrar.messenger + messenger:binaryMessenger pigeonSuffix:pigeonSuffix]; - SetUpFGMMapsInspectorApiWithSuffix(registrar.messenger, _inspector, pigeonSuffix); + SetUpFGMMapsInspectorApiWithSuffix(binaryMessenger, _inspector, pigeonSuffix); } return self; } diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapController_Test.h b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapController_Test.h index 219a1ac246e9..bbb61545cc0c 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapController_Test.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/GoogleMapController_Test.h @@ -5,6 +5,7 @@ @import Flutter; @import GoogleMaps; +#import "FGMAssetProvider.h" #import "FGMCATransactionWrapper.h" #import "GoogleMapController.h" @@ -45,11 +46,13 @@ NS_ASSUME_NONNULL_BEGIN /// @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 registrar The plugin registrar passed from Flutter. +/// @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 - registrar:(NSObject *)registrar; + assetProvider:(NSObject *)assetProvider + binaryMessenger:(NSObject *)binaryMessenger; // The main Pigeon API implementation. @property(nonatomic, strong, readonly) FGMMapCallHandler *callHandler; From 4484e099fd3a04091aa94f6fd76bae0f3b2b7cb1 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 23 Jan 2026 15:18:35 -0500 Subject: [PATCH 08/11] Remove OCMock from the build --- .../google_maps_flutter_ios/example/ios/Podfile | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Podfile b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Podfile index 391330adc7d6..c2c1dc5432d3 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Podfile +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/Podfile @@ -33,8 +33,6 @@ target 'Runner' do flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do inherit! :search_paths - - pod 'OCMock', '~> 3.9.1' end end From 638ec3e613ca2e83b866541319d45a4b1328e337 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Fri, 23 Jan 2026 15:19:43 -0500 Subject: [PATCH 09/11] Version bump --- .../google_maps_flutter/google_maps_flutter_ios/CHANGELOG.md | 4 ++++ .../google_maps_flutter/google_maps_flutter_ios/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) 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 5e577772cba2..3338803175ed 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,7 @@ +## 2.17.1 + +* Refactors code for improved testability. + ## 2.17.0 * Restructures code to prepare for SwiftPM support. 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 d2b6449e77e3..f971ae9b5678 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.17.0 +version: 2.17.1 environment: sdk: ^3.9.0 From e54d6aee31a35ddc3fdc03049b738c8e6b42d3be Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 3 Feb 2026 16:08:40 -0500 Subject: [PATCH 10/11] copypasta --- .../example/ios/RunnerTests/TestMapEventHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h index a8bd18cc9318..5babf1efda26 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h +++ b/packages/google_maps_flutter/google_maps_flutter_ios/example/ios/RunnerTests/TestMapEventHandler.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN -/// Fake implementation of FGMAssetProvider for unit tests. +/// Fake implementation of FGMMapEventDelegate for unit tests. @interface TestMapEventHandler : NSObject @end From bb1733bc87c4265372ee9864a643cebdcfbc981e Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Tue, 3 Feb 2026 16:12:04 -0500 Subject: [PATCH 11/11] Explain event delegate --- .../include/google_maps_flutter_ios/FGMMapEventDelegate.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h index 874115c0c33e..f93f1adef252 100644 --- a/packages/google_maps_flutter/google_maps_flutter_ios/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/ios/google_maps_flutter_ios/Sources/google_maps_flutter_ios/include/google_maps_flutter_ios/FGMMapEventDelegate.h @@ -9,6 +9,10 @@ NS_ASSUME_NONNULL_BEGIN /// Delegate for map event notifications. +/// +/// This is abstraction of the map event portions of FGMMapsCallbackApi, to +/// avoid coupling all the individual controllers to the Pigeon implementation +/// of event handling, and to allow for mocks/fakes in unit tests. @protocol FGMMapEventDelegate /// Called when the map camera starts moving.