From 8e78aa3923f6530c36054d765cbb1b63638031f4 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Thu, 10 Nov 2016 16:08:48 -0800 Subject: [PATCH] iOS google maps custom tile support (#770) --- components/MapUrlTile.js | 20 ++++++++--- example/App.js | 2 +- example/examples/CustomTiles.js | 15 ++++++-- .../AirMapsExplorer.xcodeproj/project.pbxproj | 13 +++++++ ios/AirGoogleMaps/AIRGoogleMap.h | 1 + ios/AirGoogleMaps/AIRGoogleMap.m | 10 ++++++ .../AIRGoogleMapURLTileManager.m | 26 ++++++++++++++ ios/AirGoogleMaps/AIRGoogleMapUrlTile.h | 15 ++++++++ ios/AirGoogleMaps/AIRGoogleMapUrlTile.m | 34 +++++++++++++++++++ .../AIRGoogleMapUrlTileManager.h | 10 ++++++ 10 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapUrlTile.h create mode 100644 ios/AirGoogleMaps/AIRGoogleMapUrlTile.m create mode 100644 ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h diff --git a/components/MapUrlTile.js b/components/MapUrlTile.js index 3ab1a8488..cf2770334 100644 --- a/components/MapUrlTile.js +++ b/components/MapUrlTile.js @@ -1,9 +1,14 @@ import React, { PropTypes } from 'react'; + import { View, - requireNativeComponent, } from 'react-native'; +import decorateMapComponent, { + USES_DEFAULT_IMPLEMENTATION, + SUPPORTED, +} from './decorateMapComponent'; + const propTypes = { ...View.propTypes, @@ -25,6 +30,7 @@ const propTypes = { class MapUrlTile extends React.Component { render() { + const AIRMapUrlTile = this.getAirComponent(); return ( @@ -54,6 +61,10 @@ class CustomTiles extends React.Component { } } +CustomTiles.propTypes = { + provider: MapView.ProviderPropType, +}; + const styles = StyleSheet.create({ container: { position: 'absolute', diff --git a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj index 84761f0be..decbbec68 100644 --- a/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj +++ b/example/ios/AirMapsExplorer.xcodeproj/project.pbxproj @@ -48,6 +48,9 @@ 8620CC931DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m in Sources */ = {isa = PBXBuildFile; fileRef = 8620CC861DBD814A00B79BFE /* RCTConvert+GMSMapViewType.m */; }; 8697D6221DBEDE6100DB7D0F /* AIRGoogleMapCircle.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */; }; 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */; }; + 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */; }; + 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */; }; + C9315A21AD5A149EB5B40F29 /* Pods_AirMapsExplorer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24EB66BA0860A4DCD4CA3D77 /* Pods_AirMapsExplorer.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -146,6 +149,10 @@ 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapCircleManager.m; sourceTree = ""; }; BE5DE1E9AE25978F88CD940A /* Pods-AirMapsExplorer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.debug.xcconfig"; sourceTree = ""; }; E138AD0CDB08FE57B09B18F8 /* Pods-AirMapsExplorer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AirMapsExplorer.release.xcconfig"; path = "Pods/Target Support Files/Pods-AirMapsExplorer/Pods-AirMapsExplorer.release.xcconfig"; sourceTree = ""; }; + 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTile.h; sourceTree = ""; }; + 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapUrlTile.m; sourceTree = ""; }; + 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AIRGoogleMapUrlTileManager.h; sourceTree = ""; }; + 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AIRGoogleMapURLTileManager.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -316,6 +323,10 @@ 8697D6211DBEDE6100DB7D0F /* AIRGoogleMapCircle.m */, 8697D6231DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.h */, 8697D6241DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m */, + 86DE6F861DCE7D21002A5053 /* AIRGoogleMapUrlTile.h */, + 86DE6F871DCE7D21002A5053 /* AIRGoogleMapUrlTile.m */, + 86DE6F891DCE8543002A5053 /* AIRGoogleMapUrlTileManager.h */, + 86DE6F8A1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m */, ); name = AirGoogleMaps; path = ../../ios/AirGoogleMaps; @@ -521,6 +532,8 @@ 2166AB3E1D82EC56007538D7 /* RCTConvert+MoreMapKit.m in Sources */, 8697D6251DBEE22B00DB7D0F /* AIRGoogleMapCircleManager.m in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 86DE6F8B1DCE8543002A5053 /* AIRGoogleMapURLTileManager.m in Sources */, + 86DE6F881DCE7D21002A5053 /* AIRGoogleMapUrlTile.m in Sources */, 2166AB331D82EC56007538D7 /* AIRMapPolygonManager.m in Sources */, 8620CC901DBD814A00B79BFE /* AIRGoogleMapPolyline.m in Sources */, 2166AB2B1D82EC56007538D7 /* AIRMapCalloutManager.m in Sources */, diff --git a/ios/AirGoogleMaps/AIRGoogleMap.h b/ios/AirGoogleMaps/AIRGoogleMap.h index e25ab4897..52480974a 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.h +++ b/ios/AirGoogleMaps/AIRGoogleMap.h @@ -27,6 +27,7 @@ @property (nonatomic, strong) NSMutableArray *polygons; @property (nonatomic, strong) NSMutableArray *polylines; @property (nonatomic, strong) NSMutableArray *circles; +@property (nonatomic, strong) NSMutableArray *tiles; @property (nonatomic, assign) BOOL showsBuildings; @property (nonatomic, assign) BOOL showsTraffic; diff --git a/ios/AirGoogleMaps/AIRGoogleMap.m b/ios/AirGoogleMaps/AIRGoogleMap.m index af3019a1b..9da6a64e7 100644 --- a/ios/AirGoogleMaps/AIRGoogleMap.m +++ b/ios/AirGoogleMaps/AIRGoogleMap.m @@ -10,6 +10,7 @@ #import "AIRGoogleMapPolygon.h" #import "AIRGoogleMapPolyline.h" #import "AIRGoogleMapCircle.h" +#import "AIRGoogleMapUrlTile.h" #import #import #import "RCTConvert+MapKit.h" @@ -44,6 +45,7 @@ - (instancetype)init _polygons = [NSMutableArray array]; _polylines = [NSMutableArray array]; _circles = [NSMutableArray array]; + _tiles = [NSMutableArray array]; _initialRegionSet = false; } return self; @@ -85,6 +87,10 @@ - (void)insertReactSubview:(id)subview atIndex:(NSInteger)atIndex AIRGoogleMapCircle *circle = (AIRGoogleMapCircle*)subview; circle.circle.map = self; [self.circles addObject:circle]; + } else if ([subview isKindOfClass:[AIRGoogleMapUrlTile class]]) { + AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; + tile.tileLayer.map = self; + [self.tiles addObject:tile]; } [_reactSubviews insertObject:(UIView *)subview atIndex:(NSUInteger) atIndex]; } @@ -112,6 +118,10 @@ - (void)removeReactSubview:(id)subview { AIRGoogleMapCircle *circle = (AIRGoogleMapCircle*)subview; circle.circle.map = nil; [self.circles removeObject:circle]; + } else if ([subview isKindOfClass:[AIRGoogleMapUrlTile class]]) { + AIRGoogleMapUrlTile *tile = (AIRGoogleMapUrlTile*)subview; + tile.tileLayer.map = nil; + [self.tiles removeObject:tile]; } [_reactSubviews removeObject:(UIView *)subview]; } diff --git a/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m b/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m new file mode 100644 index 000000000..79c82fe25 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapURLTileManager.m @@ -0,0 +1,26 @@ +// +// AIRGoogleMapURLTileManager.m +// Created by Nick Italiano on 11/5/16. +// + +#import "AIRGoogleMapUrlTileManager.h" +#import "AIRGoogleMapUrlTile.h" + +@interface AIRGoogleMapUrlTileManager() + +@end + +@implementation AIRGoogleMapUrlTileManager + +RCT_EXPORT_MODULE() + +- (UIView *)view +{ + AIRGoogleMapUrlTile *tileLayer = [AIRGoogleMapUrlTile new]; + return tileLayer; +} + +RCT_EXPORT_VIEW_PROPERTY(urlTemplate, NSString) +RCT_EXPORT_VIEW_PROPERTY(zIndex, int) + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h new file mode 100644 index 000000000..f76a9dc88 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.h @@ -0,0 +1,15 @@ +// +// AIRGoogleMapURLTile.h +// Created by Nick Italiano on 11/5/16. +// + +#import +#import + +@interface AIRGoogleMapUrlTile : UIView + +@property (nonatomic, strong) GMSURLTileLayer *tileLayer; +@property (nonatomic, assign) NSString *urlTemplate; +@property (nonatomic, assign) int zIndex; + +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m new file mode 100644 index 000000000..ae6333cff --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTile.m @@ -0,0 +1,34 @@ +// +// AIRGoogleMapURLTile.m +// Created by Nick Italiano on 11/5/16. +// + +#import "AIRGoogleMapUrlTile.h" + +@implementation AIRGoogleMapUrlTile + +- (void)setZIndex:(int)zIndex +{ + _zIndex = zIndex; + _tileLayer.zIndex = zIndex; +} + +- (void)setUrlTemplate:(NSString *)urlTemplate +{ + _urlTemplate = urlTemplate; + _tileLayer = [GMSURLTileLayer tileLayerWithURLConstructor:[self _getTileURLConstructor]]; +} + +- (GMSTileURLConstructor)_getTileURLConstructor +{ + NSString *urlTemplate = self.urlTemplate; + GMSTileURLConstructor urls = ^(NSUInteger x, NSUInteger y, NSUInteger zoom) { + NSString *url = urlTemplate; + url = [url stringByReplacingOccurrencesOfString:@"{x}" withString:[NSString stringWithFormat: @"%ld", (long)x]]; + url = [url stringByReplacingOccurrencesOfString:@"{y}" withString:[NSString stringWithFormat: @"%ld", (long)y]]; + url = [url stringByReplacingOccurrencesOfString:@"{z}" withString:[NSString stringWithFormat: @"%ld", (long)zoom]]; + return [NSURL URLWithString:url]; + }; + return urls; +} +@end diff --git a/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h b/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h new file mode 100644 index 000000000..3554837d4 --- /dev/null +++ b/ios/AirGoogleMaps/AIRGoogleMapUrlTileManager.h @@ -0,0 +1,10 @@ +// +// AIRGoogleMapURLTileManager.h +// Created by Nick Italiano on 11/5/16. +// + +#import +#import "RCTViewManager.h" + +@interface AIRGoogleMapUrlTileManager : RCTViewManager +@end