blob: 6378994819dd79952e7d4d5d8cbe3ae04d0163cf [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "GoogleMapController.h"
#import "FLTGoogleMapJSONConversions.h"
#import "FLTGoogleMapTileOverlayController.h"
#pragma mark - Conversion of JSON-like values sent via platform channels. Forward declarations.
@interface FLTGoogleMapFactory ()
@property(weak, nonatomic) NSObject<FlutterPluginRegistrar> *registrar;
@end
@implementation FLTGoogleMapFactory
- (instancetype)initWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
self = [super init];
if (self) {
_registrar = registrar;
}
return self;
}
- (NSObject<FlutterMessageCodec> *)createArgsCodec {
return [FlutterStandardMessageCodec sharedInstance];
}
- (NSObject<FlutterPlatformView> *)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args {
return [[FLTGoogleMapController alloc] initWithFrame:frame
viewIdentifier:viewId
arguments:args
registrar:self.registrar];
}
@end
@interface FLTGoogleMapController ()
@property(nonatomic, strong) GMSMapView *mapView;
@property(nonatomic, strong) FlutterMethodChannel *channel;
@property(nonatomic, assign) BOOL trackCameraPosition;
@property(nonatomic, weak) NSObject<FlutterPluginRegistrar> *registrar;
@property(nonatomic, strong) FLTMarkersController *markersController;
@property(nonatomic, strong) FLTPolygonsController *polygonsController;
@property(nonatomic, strong) FLTPolylinesController *polylinesController;
@property(nonatomic, strong) FLTCirclesController *circlesController;
@property(nonatomic, strong) FLTTileOverlaysController *tileOverlaysController;
@end
@implementation FLTGoogleMapController
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
registrar:(NSObject<FlutterPluginRegistrar> *)registrar {
GMSCameraPosition *camera =
[FLTGoogleMapJSONConversions cameraPostionFromDictionary:args[@"initialCameraPosition"]];
GMSMapView *mapView = [GMSMapView mapWithFrame:frame camera:camera];
return [self initWithMapView:mapView viewIdentifier:viewId arguments:args registrar:registrar];
}
- (instancetype)initWithMapView:(GMSMapView *_Nonnull)mapView
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
registrar:(NSObject<FlutterPluginRegistrar> *_Nonnull)registrar {
if (self = [super init]) {
_mapView = mapView;
_mapView.accessibilityElementsHidden = NO;
// TODO(cyanglaz): avoid sending message to self in the middle of the init method.
// https://github.com/flutter/flutter/issues/104121
[self interpretMapOptions:args[@"options"]];
NSString *channelName =
[NSString stringWithFormat:@"plugins.flutter.io/google_maps_%lld", viewId];
_channel = [FlutterMethodChannel methodChannelWithName:channelName
binaryMessenger:registrar.messenger];
__weak __typeof__(self) weakSelf = self;
[_channel setMethodCallHandler:^(FlutterMethodCall *call, FlutterResult result) {
if (weakSelf) {
[weakSelf onMethodCall:call result:result];
}
}];
_mapView.delegate = weakSelf;
_registrar = registrar;
_markersController = [[FLTMarkersController alloc] initWithMethodChannel:_channel
mapView:_mapView
registrar:registrar];
_polygonsController = [[FLTPolygonsController alloc] init:_channel
mapView:_mapView
registrar:registrar];
_polylinesController = [[FLTPolylinesController alloc] init:_channel
mapView:_mapView
registrar:registrar];
_circlesController = [[FLTCirclesController alloc] init:_channel
mapView:_mapView
registrar:registrar];
_tileOverlaysController = [[FLTTileOverlaysController alloc] init:_channel
mapView:_mapView
registrar:registrar];
id markersToAdd = args[@"markersToAdd"];
if ([markersToAdd isKindOfClass:[NSArray class]]) {
[_markersController addMarkers:markersToAdd];
}
id polygonsToAdd = args[@"polygonsToAdd"];
if ([polygonsToAdd isKindOfClass:[NSArray class]]) {
[_polygonsController addPolygons:polygonsToAdd];
}
id polylinesToAdd = args[@"polylinesToAdd"];
if ([polylinesToAdd isKindOfClass:[NSArray class]]) {
[_polylinesController addPolylines:polylinesToAdd];
}
id circlesToAdd = args[@"circlesToAdd"];
if ([circlesToAdd isKindOfClass:[NSArray class]]) {
[_circlesController addCircles:circlesToAdd];
}
id tileOverlaysToAdd = args[@"tileOverlaysToAdd"];
if ([tileOverlaysToAdd isKindOfClass:[NSArray class]]) {
[_tileOverlaysController addTileOverlays:tileOverlaysToAdd];
}
[_mapView addObserver:self forKeyPath:@"frame" options:0 context:nil];
}
return self;
}
- (UIView *)view {
return self.mapView;
}
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (object == self.mapView && [keyPath isEqualToString:@"frame"]) {
CGRect bounds = self.mapView.bounds;
if (CGRectEqualToRect(bounds, CGRectZero)) {
// The workaround is to fix an issue that the camera location is not current when
// the size of the map is zero at initialization.
// So We only care about the size of the `self.mapView`, ignore the frame changes when the
// size is zero.
return;
}
// We only observe the frame for initial setup.
[self.mapView removeObserver:self forKeyPath:@"frame"];
[self.mapView moveCamera:[GMSCameraUpdate setCamera:self.mapView.camera]];
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)onMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
if ([call.method isEqualToString:@"map#show"]) {
[self showAtOrigin:CGPointMake([call.arguments[@"x"] doubleValue],
[call.arguments[@"y"] doubleValue])];
result(nil);
} else if ([call.method isEqualToString:@"map#hide"]) {
[self hide];
result(nil);
} else if ([call.method isEqualToString:@"camera#animate"]) {
[self
animateWithCameraUpdate:[FLTGoogleMapJSONConversions
cameraUpdateFromChannelValue:call.arguments[@"cameraUpdate"]]];
result(nil);
} else if ([call.method isEqualToString:@"camera#move"]) {
[self moveWithCameraUpdate:[FLTGoogleMapJSONConversions
cameraUpdateFromChannelValue:call.arguments[@"cameraUpdate"]]];
result(nil);
} else if ([call.method isEqualToString:@"map#update"]) {
[self interpretMapOptions:call.arguments[@"options"]];
result([FLTGoogleMapJSONConversions dictionaryFromPosition:[self cameraPosition]]);
} else if ([call.method isEqualToString:@"map#getVisibleRegion"]) {
if (self.mapView != nil) {
GMSVisibleRegion visibleRegion = self.mapView.projection.visibleRegion;
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] initWithRegion:visibleRegion];
result([FLTGoogleMapJSONConversions dictionaryFromCoordinateBounds:bounds]);
} else {
result([FlutterError errorWithCode:@"GoogleMap uninitialized"
message:@"getVisibleRegion called prior to map initialization"
details:nil]);
}
} else if ([call.method isEqualToString:@"map#getScreenCoordinate"]) {
if (self.mapView != nil) {
CLLocationCoordinate2D location =
[FLTGoogleMapJSONConversions locationFromLatLong:call.arguments];
CGPoint point = [self.mapView.projection pointForCoordinate:location];
result([FLTGoogleMapJSONConversions dictionaryFromPoint:point]);
} else {
result([FlutterError errorWithCode:@"GoogleMap uninitialized"
message:@"getScreenCoordinate called prior to map initialization"
details:nil]);
}
} else if ([call.method isEqualToString:@"map#getLatLng"]) {
if (self.mapView != nil && call.arguments) {
CGPoint point = [FLTGoogleMapJSONConversions pointFromDictionary:call.arguments];
CLLocationCoordinate2D latlng = [self.mapView.projection coordinateForPoint:point];
result([FLTGoogleMapJSONConversions arrayFromLocation:latlng]);
} else {
result([FlutterError errorWithCode:@"GoogleMap uninitialized"
message:@"getLatLng called prior to map initialization"
details:nil]);
}
} else if ([call.method isEqualToString:@"map#waitForMap"]) {
result(nil);
} else if ([call.method isEqualToString:@"map#takeSnapshot"]) {
if (@available(iOS 10.0, *)) {
if (self.mapView != nil) {
UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat defaultFormat];
format.scale = [[UIScreen mainScreen] scale];
UIGraphicsImageRenderer *renderer =
[[UIGraphicsImageRenderer alloc] initWithSize:self.mapView.frame.size format:format];
UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
[self.mapView.layer renderInContext:context.CGContext];
}];
result([FlutterStandardTypedData typedDataWithBytes:UIImagePNGRepresentation(image)]);
} else {
result([FlutterError errorWithCode:@"GoogleMap uninitialized"
message:@"takeSnapshot called prior to map initialization"
details:nil]);
}
} else {
NSLog(@"Taking snapshots is not supported for Flutter Google Maps prior to iOS 10.");
result(nil);
}
} else if ([call.method isEqualToString:@"markers#update"]) {
id markersToAdd = call.arguments[@"markersToAdd"];
if ([markersToAdd isKindOfClass:[NSArray class]]) {
[self.markersController addMarkers:markersToAdd];
}
id markersToChange = call.arguments[@"markersToChange"];
if ([markersToChange isKindOfClass:[NSArray class]]) {
[self.markersController changeMarkers:markersToChange];
}
id markerIdsToRemove = call.arguments[@"markerIdsToRemove"];
if ([markerIdsToRemove isKindOfClass:[NSArray class]]) {
[self.markersController removeMarkersWithIdentifiers:markerIdsToRemove];
}
result(nil);
} else if ([call.method isEqualToString:@"markers#showInfoWindow"]) {
id markerId = call.arguments[@"markerId"];
if ([markerId isKindOfClass:[NSString class]]) {
[self.markersController showMarkerInfoWindowWithIdentifier:markerId result:result];
} else {
result([FlutterError errorWithCode:@"Invalid markerId"
message:@"showInfoWindow called with invalid markerId"
details:nil]);
}
} else if ([call.method isEqualToString:@"markers#hideInfoWindow"]) {
id markerId = call.arguments[@"markerId"];
if ([markerId isKindOfClass:[NSString class]]) {
[self.markersController hideMarkerInfoWindowWithIdentifier:markerId result:result];
} else {
result([FlutterError errorWithCode:@"Invalid markerId"
message:@"hideInfoWindow called with invalid markerId"
details:nil]);
}
} else if ([call.method isEqualToString:@"markers#isInfoWindowShown"]) {
id markerId = call.arguments[@"markerId"];
if ([markerId isKindOfClass:[NSString class]]) {
[self.markersController isInfoWindowShownForMarkerWithIdentifier:markerId result:result];
} else {
result([FlutterError errorWithCode:@"Invalid markerId"
message:@"isInfoWindowShown called with invalid markerId"
details:nil]);
}
} else if ([call.method isEqualToString:@"polygons#update"]) {
id polygonsToAdd = call.arguments[@"polygonsToAdd"];
if ([polygonsToAdd isKindOfClass:[NSArray class]]) {
[self.polygonsController addPolygons:polygonsToAdd];
}
id polygonsToChange = call.arguments[@"polygonsToChange"];
if ([polygonsToChange isKindOfClass:[NSArray class]]) {
[self.polygonsController changePolygons:polygonsToChange];
}
id polygonIdsToRemove = call.arguments[@"polygonIdsToRemove"];
if ([polygonIdsToRemove isKindOfClass:[NSArray class]]) {
[self.polygonsController removePolygonWithIdentifiers:polygonIdsToRemove];
}
result(nil);
} else if ([call.method isEqualToString:@"polylines#update"]) {
id polylinesToAdd = call.arguments[@"polylinesToAdd"];
if ([polylinesToAdd isKindOfClass:[NSArray class]]) {
[self.polylinesController addPolylines:polylinesToAdd];
}
id polylinesToChange = call.arguments[@"polylinesToChange"];
if ([polylinesToChange isKindOfClass:[NSArray class]]) {
[self.polylinesController changePolylines:polylinesToChange];
}
id polylineIdsToRemove = call.arguments[@"polylineIdsToRemove"];
if ([polylineIdsToRemove isKindOfClass:[NSArray class]]) {
[self.polylinesController removePolylineWithIdentifiers:polylineIdsToRemove];
}
result(nil);
} else if ([call.method isEqualToString:@"circles#update"]) {
id circlesToAdd = call.arguments[@"circlesToAdd"];
if ([circlesToAdd isKindOfClass:[NSArray class]]) {
[self.circlesController addCircles:circlesToAdd];
}
id circlesToChange = call.arguments[@"circlesToChange"];
if ([circlesToChange isKindOfClass:[NSArray class]]) {
[self.circlesController changeCircles:circlesToChange];
}
id circleIdsToRemove = call.arguments[@"circleIdsToRemove"];
if ([circleIdsToRemove isKindOfClass:[NSArray class]]) {
[self.circlesController removeCircleWithIdentifiers:circleIdsToRemove];
}
result(nil);
} else if ([call.method isEqualToString:@"tileOverlays#update"]) {
id tileOverlaysToAdd = call.arguments[@"tileOverlaysToAdd"];
if ([tileOverlaysToAdd isKindOfClass:[NSArray class]]) {
[self.tileOverlaysController addTileOverlays:tileOverlaysToAdd];
}
id tileOverlaysToChange = call.arguments[@"tileOverlaysToChange"];
if ([tileOverlaysToChange isKindOfClass:[NSArray class]]) {
[self.tileOverlaysController changeTileOverlays:tileOverlaysToChange];
}
id tileOverlayIdsToRemove = call.arguments[@"tileOverlayIdsToRemove"];
if ([tileOverlayIdsToRemove isKindOfClass:[NSArray class]]) {
[self.tileOverlaysController removeTileOverlayWithIdentifiers:tileOverlayIdsToRemove];
}
result(nil);
} else if ([call.method isEqualToString:@"tileOverlays#clearTileCache"]) {
id rawTileOverlayId = call.arguments[@"tileOverlayId"];
[self.tileOverlaysController clearTileCacheWithIdentifier:rawTileOverlayId];
result(nil);
} else if ([call.method isEqualToString:@"map#isCompassEnabled"]) {
NSNumber *isCompassEnabled = @(self.mapView.settings.compassButton);
result(isCompassEnabled);
} else if ([call.method isEqualToString:@"map#isMapToolbarEnabled"]) {
NSNumber *isMapToolbarEnabled = @NO;
result(isMapToolbarEnabled);
} else if ([call.method isEqualToString:@"map#getMinMaxZoomLevels"]) {
NSArray *zoomLevels = @[ @(self.mapView.minZoom), @(self.mapView.maxZoom) ];
result(zoomLevels);
} else if ([call.method isEqualToString:@"map#getZoomLevel"]) {
result(@(self.mapView.camera.zoom));
} else if ([call.method isEqualToString:@"map#isZoomGesturesEnabled"]) {
NSNumber *isZoomGesturesEnabled = @(self.mapView.settings.zoomGestures);
result(isZoomGesturesEnabled);
} else if ([call.method isEqualToString:@"map#isZoomControlsEnabled"]) {
NSNumber *isZoomControlsEnabled = @NO;
result(isZoomControlsEnabled);
} else if ([call.method isEqualToString:@"map#isTiltGesturesEnabled"]) {
NSNumber *isTiltGesturesEnabled = @(self.mapView.settings.tiltGestures);
result(isTiltGesturesEnabled);
} else if ([call.method isEqualToString:@"map#isRotateGesturesEnabled"]) {
NSNumber *isRotateGesturesEnabled = @(self.mapView.settings.rotateGestures);
result(isRotateGesturesEnabled);
} else if ([call.method isEqualToString:@"map#isScrollGesturesEnabled"]) {
NSNumber *isScrollGesturesEnabled = @(self.mapView.settings.scrollGestures);
result(isScrollGesturesEnabled);
} else if ([call.method isEqualToString:@"map#isMyLocationButtonEnabled"]) {
NSNumber *isMyLocationButtonEnabled = @(self.mapView.settings.myLocationButton);
result(isMyLocationButtonEnabled);
} else if ([call.method isEqualToString:@"map#isTrafficEnabled"]) {
NSNumber *isTrafficEnabled = @(self.mapView.trafficEnabled);
result(isTrafficEnabled);
} else if ([call.method isEqualToString:@"map#isBuildingsEnabled"]) {
NSNumber *isBuildingsEnabled = @(self.mapView.buildingsEnabled);
result(isBuildingsEnabled);
} else if ([call.method isEqualToString:@"map#setStyle"]) {
NSString *mapStyle = [call arguments];
NSString *error = [self setMapStyle:mapStyle];
if (error == nil) {
result(@[ @(YES) ]);
} else {
result(@[ @(NO), error ]);
}
} else if ([call.method isEqualToString:@"map#getTileOverlayInfo"]) {
NSString *rawTileOverlayId = call.arguments[@"tileOverlayId"];
result([self.tileOverlaysController tileOverlayInfoWithIdentifier:rawTileOverlayId]);
} else {
result(FlutterMethodNotImplemented);
}
}
- (void)showAtOrigin:(CGPoint)origin {
CGRect frame = {origin, self.mapView.frame.size};
self.mapView.frame = frame;
self.mapView.hidden = NO;
}
- (void)hide {
self.mapView.hidden = YES;
}
- (void)animateWithCameraUpdate:(GMSCameraUpdate *)cameraUpdate {
[self.mapView animateWithCameraUpdate:cameraUpdate];
}
- (void)moveWithCameraUpdate:(GMSCameraUpdate *)cameraUpdate {
[self.mapView moveCamera:cameraUpdate];
}
- (GMSCameraPosition *)cameraPosition {
if (self.trackCameraPosition) {
return self.mapView.camera;
} else {
return nil;
}
}
- (void)setCamera:(GMSCameraPosition *)camera {
self.mapView.camera = camera;
}
- (void)setCameraTargetBounds:(GMSCoordinateBounds *)bounds {
self.mapView.cameraTargetBounds = bounds;
}
- (void)setCompassEnabled:(BOOL)enabled {
self.mapView.settings.compassButton = enabled;
}
- (void)setIndoorEnabled:(BOOL)enabled {
self.mapView.indoorEnabled = enabled;
}
- (void)setTrafficEnabled:(BOOL)enabled {
self.mapView.trafficEnabled = enabled;
}
- (void)setBuildingsEnabled:(BOOL)enabled {
self.mapView.buildingsEnabled = enabled;
}
- (void)setMapType:(GMSMapViewType)mapType {
self.mapView.mapType = mapType;
}
- (void)setMinZoom:(float)minZoom maxZoom:(float)maxZoom {
[self.mapView setMinZoom:minZoom maxZoom:maxZoom];
}
- (void)setPaddingTop:(float)top left:(float)left bottom:(float)bottom right:(float)right {
self.mapView.padding = UIEdgeInsetsMake(top, left, bottom, right);
}
- (void)setRotateGesturesEnabled:(BOOL)enabled {
self.mapView.settings.rotateGestures = enabled;
}
- (void)setScrollGesturesEnabled:(BOOL)enabled {
self.mapView.settings.scrollGestures = enabled;
}
- (void)setTiltGesturesEnabled:(BOOL)enabled {
self.mapView.settings.tiltGestures = enabled;
}
- (void)setTrackCameraPosition:(BOOL)enabled {
_trackCameraPosition = enabled;
}
- (void)setZoomGesturesEnabled:(BOOL)enabled {
self.mapView.settings.zoomGestures = enabled;
}
- (void)setMyLocationEnabled:(BOOL)enabled {
self.mapView.myLocationEnabled = enabled;
}
- (void)setMyLocationButtonEnabled:(BOOL)enabled {
self.mapView.settings.myLocationButton = enabled;
}
- (NSString *)setMapStyle:(NSString *)mapStyle {
if (mapStyle == (id)[NSNull null] || mapStyle.length == 0) {
self.mapView.mapStyle = nil;
return nil;
}
NSError *error;
GMSMapStyle *style = [GMSMapStyle styleWithJSONString:mapStyle error:&error];
if (!style) {
return [error localizedDescription];
} else {
self.mapView.mapStyle = style;
return nil;
}
}
#pragma mark - GMSMapViewDelegate methods
- (void)mapView:(GMSMapView *)mapView willMove:(BOOL)gesture {
[self.channel invokeMethod:@"camera#onMoveStarted" arguments:@{@"isGesture" : @(gesture)}];
}
- (void)mapView:(GMSMapView *)mapView didChangeCameraPosition:(GMSCameraPosition *)position {
if (self.trackCameraPosition) {
[self.channel invokeMethod:@"camera#onMove"
arguments:@{
@"position" : [FLTGoogleMapJSONConversions dictionaryFromPosition:position]
}];
}
}
- (void)mapView:(GMSMapView *)mapView idleAtCameraPosition:(GMSCameraPosition *)position {
[self.channel invokeMethod:@"camera#onIdle" arguments:@{}];
}
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker {
NSString *markerId = marker.userData[0];
return [self.markersController didTapMarkerWithIdentifier:markerId];
}
- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker {
NSString *markerId = marker.userData[0];
[self.markersController didEndDraggingMarkerWithIdentifier:markerId location:marker.position];
}
- (void)mapView:(GMSMapView *)mapView didStartDraggingMarker:(GMSMarker *)marker {
NSString *markerId = marker.userData[0];
[self.markersController didStartDraggingMarkerWithIdentifier:markerId location:marker.position];
}
- (void)mapView:(GMSMapView *)mapView didDragMarker:(GMSMarker *)marker {
NSString *markerId = marker.userData[0];
[self.markersController didDragMarkerWithIdentifier:markerId location:marker.position];
}
- (void)mapView:(GMSMapView *)mapView didTapInfoWindowOfMarker:(GMSMarker *)marker {
NSString *markerId = marker.userData[0];
[self.markersController didTapInfoWindowOfMarkerWithIdentifier:markerId];
}
- (void)mapView:(GMSMapView *)mapView didTapOverlay:(GMSOverlay *)overlay {
NSString *overlayId = overlay.userData[0];
if ([self.polylinesController hasPolylineWithIdentifier:overlayId]) {
[self.polylinesController didTapPolylineWithIdentifier:overlayId];
} else if ([self.polygonsController hasPolygonWithIdentifier:overlayId]) {
[self.polygonsController didTapPolygonWithIdentifier:overlayId];
} else if ([self.circlesController hasCircleWithIdentifier:overlayId]) {
[self.circlesController didTapCircleWithIdentifier:overlayId];
}
}
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
[self.channel
invokeMethod:@"map#onTap"
arguments:@{@"position" : [FLTGoogleMapJSONConversions arrayFromLocation:coordinate]}];
}
- (void)mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate {
[self.channel
invokeMethod:@"map#onLongPress"
arguments:@{@"position" : [FLTGoogleMapJSONConversions arrayFromLocation:coordinate]}];
}
- (void)interpretMapOptions:(NSDictionary *)data {
NSArray *cameraTargetBounds = data[@"cameraTargetBounds"];
if (cameraTargetBounds && cameraTargetBounds != (id)[NSNull null]) {
[self
setCameraTargetBounds:cameraTargetBounds.count > 0 && cameraTargetBounds[0] != [NSNull null]
? [FLTGoogleMapJSONConversions
coordinateBoundsFromLatLongs:cameraTargetBounds.firstObject]
: nil];
}
NSNumber *compassEnabled = data[@"compassEnabled"];
if (compassEnabled && compassEnabled != (id)[NSNull null]) {
[self setCompassEnabled:[compassEnabled boolValue]];
}
id indoorEnabled = data[@"indoorEnabled"];
if (indoorEnabled && indoorEnabled != [NSNull null]) {
[self setIndoorEnabled:[indoorEnabled boolValue]];
}
id trafficEnabled = data[@"trafficEnabled"];
if (trafficEnabled && trafficEnabled != [NSNull null]) {
[self setTrafficEnabled:[trafficEnabled boolValue]];
}
id buildingsEnabled = data[@"buildingsEnabled"];
if (buildingsEnabled && buildingsEnabled != [NSNull null]) {
[self setBuildingsEnabled:[buildingsEnabled boolValue]];
}
id mapType = data[@"mapType"];
if (mapType && mapType != [NSNull null]) {
[self setMapType:[FLTGoogleMapJSONConversions mapViewTypeFromTypeValue:mapType]];
}
NSArray *zoomData = data[@"minMaxZoomPreference"];
if (zoomData && zoomData != (id)[NSNull null]) {
float minZoom = (zoomData[0] == [NSNull null]) ? kGMSMinZoomLevel : [zoomData[0] floatValue];
float maxZoom = (zoomData[1] == [NSNull null]) ? kGMSMaxZoomLevel : [zoomData[1] floatValue];
[self setMinZoom:minZoom maxZoom:maxZoom];
}
NSArray *paddingData = data[@"padding"];
if (paddingData) {
float top = (paddingData[0] == [NSNull null]) ? 0 : [paddingData[0] floatValue];
float left = (paddingData[1] == [NSNull null]) ? 0 : [paddingData[1] floatValue];
float bottom = (paddingData[2] == [NSNull null]) ? 0 : [paddingData[2] floatValue];
float right = (paddingData[3] == [NSNull null]) ? 0 : [paddingData[3] floatValue];
[self setPaddingTop:top left:left bottom:bottom right:right];
}
NSNumber *rotateGesturesEnabled = data[@"rotateGesturesEnabled"];
if (rotateGesturesEnabled && rotateGesturesEnabled != (id)[NSNull null]) {
[self setRotateGesturesEnabled:[rotateGesturesEnabled boolValue]];
}
NSNumber *scrollGesturesEnabled = data[@"scrollGesturesEnabled"];
if (scrollGesturesEnabled && scrollGesturesEnabled != (id)[NSNull null]) {
[self setScrollGesturesEnabled:[scrollGesturesEnabled boolValue]];
}
NSNumber *tiltGesturesEnabled = data[@"tiltGesturesEnabled"];
if (tiltGesturesEnabled && tiltGesturesEnabled != (id)[NSNull null]) {
[self setTiltGesturesEnabled:[tiltGesturesEnabled boolValue]];
}
NSNumber *trackCameraPosition = data[@"trackCameraPosition"];
if (trackCameraPosition && trackCameraPosition != (id)[NSNull null]) {
[self setTrackCameraPosition:[trackCameraPosition boolValue]];
}
NSNumber *zoomGesturesEnabled = data[@"zoomGesturesEnabled"];
if (zoomGesturesEnabled && zoomGesturesEnabled != (id)[NSNull null]) {
[self setZoomGesturesEnabled:[zoomGesturesEnabled boolValue]];
}
NSNumber *myLocationEnabled = data[@"myLocationEnabled"];
if (myLocationEnabled && myLocationEnabled != (id)[NSNull null]) {
[self setMyLocationEnabled:[myLocationEnabled boolValue]];
}
NSNumber *myLocationButtonEnabled = data[@"myLocationButtonEnabled"];
if (myLocationButtonEnabled && myLocationButtonEnabled != (id)[NSNull null]) {
[self setMyLocationButtonEnabled:[myLocationButtonEnabled boolValue]];
}
}
@end