From 3ddb8dfc86753120d2ea2c3befdf2430c1c56562 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Thu, 22 Sep 2016 17:30:47 -0700 Subject: [ios, macos] Add tile template option to raster and vector sources A new MGLTileSet class that wraps all available core Tileset options can be created and passed into the sources. The sources pass that tileset object along to core. --- platform/darwin/src/MGLRasterSource.h | 12 ++++- platform/darwin/src/MGLRasterSource.mm | 37 +++++++++++-- platform/darwin/src/MGLTileSet.h | 78 +++++++++++++++++++++++++++ platform/darwin/src/MGLTileSet.mm | 87 ++++++++++++++++++++++++++++++ platform/darwin/src/MGLTileSet_Private.h | 9 ++++ platform/darwin/src/MGLVectorSource.h | 10 ++++ platform/darwin/src/MGLVectorSource.mm | 31 +++++++++-- platform/ios/ios.xcodeproj/project.pbxproj | 22 ++++++++ platform/ios/src/Mapbox.h | 1 + platform/ios/test/MGLTileSetTests.mm | 82 ++++++++++++++++++++++++++++ 10 files changed, 360 insertions(+), 9 deletions(-) create mode 100644 platform/darwin/src/MGLTileSet.h create mode 100644 platform/darwin/src/MGLTileSet.mm create mode 100644 platform/darwin/src/MGLTileSet_Private.h create mode 100644 platform/ios/test/MGLTileSetTests.mm diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h index e563244bce..3b22257cb6 100644 --- a/platform/darwin/src/MGLRasterSource.h +++ b/platform/darwin/src/MGLRasterSource.h @@ -1,10 +1,20 @@ #import "MGLSource.h" +#import "MGLTypes.h" + +@class MGLTileSet; + +NS_ASSUME_NONNULL_BEGIN @interface MGLRasterSource : MGLSource @property (nonatomic, readonly, copy) NSURL *URL; -@property (nonatomic, readonly, assign) CGFloat tileSize; +@property (nonatomic, readonly, assign) NSUInteger tileSize; +@property (nonatomic, readonly, nullable) MGLTileSet *tileSet; - (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url tileSize:(CGFloat)tileSize; +- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier tileSize:(CGFloat)tileSize tileSet:(MGLTileSet *)tileSet; + @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm index 15ca2fc558..06d5a9689c 100644 --- a/platform/darwin/src/MGLRasterSource.mm +++ b/platform/darwin/src/MGLRasterSource.mm @@ -1,12 +1,15 @@ #import "MGLRasterSource.h" #import "MGLSource_Private.h" +#import "MGLTileSet_Private.h" +#import "NSURL+MGLAdditions.h" #include @implementation MGLRasterSource -- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url tileSize:(CGFloat)tileSize { +- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url tileSize:(CGFloat)tileSize +{ if (self = [super initWithSourceIdentifier:sourceIdentifier]) { _URL = url; _tileSize = tileSize; @@ -14,10 +17,34 @@ return self; } -- (std::unique_ptr)mbglSource { - auto source = std::make_unique(self.sourceIdentifier.UTF8String, - self.URL.absoluteString.UTF8String, - uint16_t(self.tileSize)); +- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier tileSize:(CGFloat)tileSize tileSet:(MGLTileSet *)tileSet; +{ + if (self = [super initWithSourceIdentifier:sourceIdentifier]) + { + _tileSize = tileSize; + _tileSet = tileSet; + } + return self; +} + +- (std::unique_ptr)mbglSource +{ + std::unique_ptr source; + + if (self.URL) + { + source = std::make_unique(self.sourceIdentifier.UTF8String, + self.URL.mgl_URLByStandardizingScheme.absoluteString.UTF8String, + uint16_t(self.tileSize)); + } + else + { + source = std::make_unique(self.sourceIdentifier.UTF8String, + self.tileSet.mbglTileset, + uint16_t(self.tileSize)); + + } + return std::move(source); } diff --git a/platform/darwin/src/MGLTileSet.h b/platform/darwin/src/MGLTileSet.h new file mode 100644 index 0000000000..5ae899d833 --- /dev/null +++ b/platform/darwin/src/MGLTileSet.h @@ -0,0 +1,78 @@ +#import +#import "MGLTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +/** These constants represent the scheme that the tile URL templates will use. */ +typedef NS_ENUM(NSUInteger, MGLTileSetScheme) { + MGLTileSetSchemeXYZ = 0, + MGLTileSetSchemeTMS +}; + +/** + The `MGLTileSet` class holds the tile URL template strings and associated + configuration for those strings. It can be passed to an `MGLVectorSource` or + `MGLRasterSource` instead of an `NSURL` representing a TileJSON URL to create a + source. + */ +@interface MGLTileSet : NSObject + +/** + An `NSArray` of `NSString` objects that represent the tile templates. + */ +@property (nonatomic, copy) NS_ARRAY_OF(NSString *) *tileURLTemplates; + +/** + An `NSNumber` object containing an integer; specifies the minimum zoom level at + which the source will display tiles. The value should be in the range of 0 to + 22. The default value is 0 and the source will use the default value + if `minimumZoomLevel` is nil. + */ +@property (nonatomic, nullable) NSNumber *minimumZoomLevel; + +/** + An `NSNumber` object containing an integer; specifies the maximum zoom level at + which to display tiles. The value should be in the range of 0 to 22 and greater + than `minimumZoomLevel`. The default value is 22 and the source will use the + default value if `maximumZoomLevel` is nil. + */ +@property (nonatomic, nullable) NSNumber *maximumZoomLevel; + +/** + An `NSString` object that contains an attribution to be displayed when the map is + shown to a user. The default value is nil. + */ +@property (nonatomic, copy, nullable) NSString *attribution; + +/** + An `MGLTileSetScheme` value that contains an enumeration (either + `MGLTileSetSchemeXYZ` or `MGLTileSetSchemeTMS`) that influences the y direction + of the tile coordinates. The default is `MGLTileSetSchemeXYZ`. + */ +@property (nonatomic) MGLTileSetScheme scheme; + +/** + Initializes and returns a new tile set object. + + @param tileURLTemplates An `NSArray` of `NSString` objects that represent the + tile templates. + @return The initialized tile set object. + */ +- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates; + +/** + Initializes and returns a new tile set object. + + @param tileURLTemplates An `NSArray` of `NSString` objects that represent the + tile templates. + @param minimumZoomLevel An `NSUInteger`; specifies the minimum zoom level at + which to display tiles. + @param maximumZoomLevel An `NSUInteger`; specifies the maximum zoom level at + which to display tiles. + @return The initialized tile set object. + */ +- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSUInteger)minimumZoomLevel maximumZoomLevel:(NSUInteger)maximumZoomLevel; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLTileSet.mm b/platform/darwin/src/MGLTileSet.mm new file mode 100644 index 0000000000..b2359bb92d --- /dev/null +++ b/platform/darwin/src/MGLTileSet.mm @@ -0,0 +1,87 @@ +#import "MGLTileSet.h" + +#include + +@implementation MGLTileSet + +- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates +{ + if (self = [super init]) + { + _tileURLTemplates = tileURLTemplates; + } + return self; +} + +- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSUInteger)minimumZoomLevel maximumZoomLevel:(NSUInteger)maximumZoomLevel +{ + if (minimumZoomLevel > maximumZoomLevel) + { + [[NSException exceptionWithName:@"Invalid minimumZoomLevel" + reason:@"minimumZoomLevel must be less than maximumZoomLevel" + userInfo:nil] raise]; + return nil; + } + + if (self = [super init]) + { + _tileURLTemplates = tileURLTemplates; + _minimumZoomLevel = @(minimumZoomLevel); + _maximumZoomLevel = @(maximumZoomLevel); + } + return self; +} + +- (void)setMinimumZoomLevel:(NSNumber *)minimumZoomLevel +{ + if (self.maximumZoomLevel && [minimumZoomLevel integerValue] > [self.maximumZoomLevel integerValue]) + { + [[NSException exceptionWithName:@"Invalid minimumZoomLevel" + reason:@"minimumZoomLevel must be less than maximumZoomLevel" + userInfo:nil] raise]; + return; + } + + _minimumZoomLevel = minimumZoomLevel; +} + +- (void)setMaximumZoomLevel:(NSNumber *)maximumZoomLevel +{ + if (self.maximumZoomLevel && [maximumZoomLevel integerValue] < [self.maximumZoomLevel integerValue]) + { + [[NSException exceptionWithName:@"Invalid minimumZoomLevel" + reason:@"minimumZoomLevel must be less than maximumZoomLevel" + userInfo:nil] raise]; + } + + _maximumZoomLevel = maximumZoomLevel; +} + +- (mbgl::Tileset)mbglTileset +{ + mbgl::Tileset tileset; + + for (NSString *tileURLTemplate in self.tileURLTemplates) + { + tileset.tiles.push_back(tileURLTemplate.UTF8String); + } + + // set the minimum / maximum zoom range to the values specified by this class if they + // were set. otherwise, use the core objects default values + uint8_t minimumZoomLevel = self.minimumZoomLevel ? [self.minimumZoomLevel unsignedIntegerValue] : tileset.zoomRange.min; + uint8_t maximumZoomLevel = self.minimumZoomLevel ? [self.maximumZoomLevel unsignedIntegerValue] : tileset.zoomRange.max; + tileset.zoomRange = mbgl::Range(minimumZoomLevel, maximumZoomLevel); + + if (self.attribution) + { + tileset.attribution = self.attribution.UTF8String; + } + + if (self.scheme == MGLTileSetSchemeTMS) { + tileset.scheme = mbgl::Tileset::Scheme::TMS; + } + + return tileset; +} + +@end diff --git a/platform/darwin/src/MGLTileSet_Private.h b/platform/darwin/src/MGLTileSet_Private.h new file mode 100644 index 0000000000..6a14d428db --- /dev/null +++ b/platform/darwin/src/MGLTileSet_Private.h @@ -0,0 +1,9 @@ +#import "MGLTileSet.h" + +#include + +@interface MGLTileSet (Private) + +- (mbgl::Tileset)mbglTileset; + +@end \ No newline at end of file diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h index 05e041511e..2402208499 100644 --- a/platform/darwin/src/MGLVectorSource.h +++ b/platform/darwin/src/MGLVectorSource.h @@ -1,4 +1,9 @@ #import "MGLSource.h" +#import "MGLTypes.h" + +@class MGLTileSet; + +NS_ASSUME_NONNULL_BEGIN /** A vector tile source. Tiles must be in Mapbox Vector Tile format. @@ -9,6 +14,7 @@ @interface MGLVectorSource : MGLSource @property (nonatomic, readonly, copy) NSURL *URL; +@property (nonatomic, readonly, nullable) MGLTileSet *tileSet; /** Initializes and returns a vector source from a remote url. @@ -20,4 +26,8 @@ */ - (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url; +- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier tileSet:(MGLTileSet *)tileSet; + @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index d0c9b0126a..2ab9627ef5 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -1,6 +1,8 @@ #import "MGLVectorSource.h" #import "MGLSource_Private.h" +#import "MGLTileSet_Private.h" +#import "NSURL+MGLAdditions.h" #include @@ -8,16 +10,39 @@ static NSString *MGLVectorSourceType = @"vector"; -- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url { - if (self = [super initWithSourceIdentifier:sourceIdentifier]) { +- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier URL:(NSURL *)url +{ + if (self = [super initWithSourceIdentifier:sourceIdentifier]) + { _URL = url; } return self; } +- (instancetype)initWithSourceIdentifier:(NSString *)sourceIdentifier tileSet:(MGLTileSet *)tileSet +{ + if (self = [super initWithSourceIdentifier:sourceIdentifier]) + { + _tileSet = tileSet; + } + return self; +} + - (std::unique_ptr)mbglSource { - auto source = std::make_unique(self.sourceIdentifier.UTF8String, self.URL.absoluteString.UTF8String); + std::unique_ptr source; + + if (self.URL) + { + source = std::make_unique(self.sourceIdentifier.UTF8String, + self.URL.mgl_URLByStandardizingScheme.absoluteString.UTF8String); + } + else + { + source = std::make_unique(self.sourceIdentifier.UTF8String, + self.tileSet.mbglTileset); + } + return std::move(source); } diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 35a1075301..de77398582 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -159,6 +159,13 @@ 4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4018B1CB1CDC288E00F666AF /* MGLAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */; }; + 404C26E21D89B877000AA13D /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 404C26E31D89B877000AA13D /* MGLTileSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E01D89B877000AA13D /* MGLTileSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 404C26E41D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; }; + 404C26E51D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; }; + 404C26E71D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; }; + 404C26E81D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; }; + 4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */; }; 40CFA6511D7875BB008103BD /* MGLGeoJSONSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */; }; 40EDA1C01CFE0E0200D9EA68 /* MGLAnnotationContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */; }; 40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */; }; @@ -568,6 +575,10 @@ 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationView.h; sourceTree = ""; }; 402E9DE01CD2C76200FD4519 /* Mapbox.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Mapbox.playground; sourceTree = ""; }; 404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView_Private.h; sourceTree = ""; }; + 404C26E01D89B877000AA13D /* MGLTileSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSet.h; sourceTree = ""; }; + 404C26E11D89B877000AA13D /* MGLTileSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSet.mm; sourceTree = ""; }; + 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTileSet_Private.h; sourceTree = ""; }; + 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSetTests.mm; sourceTree = ""; }; 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLGeoJSONSourceTests.mm; sourceTree = ""; }; 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView.h; sourceTree = ""; }; 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationContainerView.m; sourceTree = ""; }; @@ -812,6 +823,9 @@ 3566C7651D4A77BA008152BC /* MGLGeoJSONSource.mm */, 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */, 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */, + 404C26E01D89B877000AA13D /* MGLTileSet.h */, + 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */, + 404C26E11D89B877000AA13D /* MGLTileSet.mm */, ); name = Sources; sourceTree = ""; @@ -927,6 +941,7 @@ isa = PBXGroup; children = ( 40CFA6501D787579008103BD /* MGLGeoJSONSourceTests.mm */, + 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */, ); name = Sources; sourceTree = ""; @@ -1453,11 +1468,13 @@ 350098CA1D482D9C004B2AF0 /* NSArray+MGLStyleAttributeAdditions.h in Headers */, 350098AF1D47E6F4004B2AF0 /* UIColor+MGLStyleAttributeAdditions.h in Headers */, 3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */, + 404C26E71D89C55D000AA13D /* MGLTileSet_Private.h in Headers */, DA88485C1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h in Headers */, DA8848871CBB033F00AB86E3 /* Fabric.h in Headers */, 350098D81D4830D5004B2AF0 /* NSString+MGLStyleAttributeAdditions_Private.h in Headers */, 35305D4A1D22AA6A0007D005 /* NSData+MGLAdditions.h in Headers */, 359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */, + 404C26E21D89B877000AA13D /* MGLTileSet.h in Headers */, DA8848841CBB033F00AB86E3 /* FABAttributes.h in Headers */, DA8847FD1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h in Headers */, DA88482F1CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.h in Headers */, @@ -1489,6 +1506,7 @@ 3566C7671D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */, DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */, DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, + 404C26E31D89B877000AA13D /* MGLTileSet.h in Headers */, DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */, 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */, 35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */, @@ -1515,6 +1533,7 @@ 350098B01D47E6F4004B2AF0 /* UIColor+MGLStyleAttributeAdditions.h in Headers */, DABFB8671CBE99E500D62B32 /* MGLPolygon.h in Headers */, 350098C71D48288B004B2AF0 /* NSNumber+MGLStyleAttributeAdditions_Private.h in Headers */, + 404C26E81D89C55D000AA13D /* MGLTileSet_Private.h in Headers */, 3593E5221D529C29006D9365 /* MGLStyleAttribute.h in Headers */, DABFB8651CBE99E500D62B32 /* MGLOverlay.h in Headers */, 35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */, @@ -1857,6 +1876,7 @@ DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */, DA35A2C61CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */, 3575798E1D502EC7000B822E /* MGLRuntimeStylingHelper.m in Sources */, + 4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */, 357579851D502AF5000B822E /* MGLSymbolStyleLayerTests.m in Sources */, 357579871D502AFE000B822E /* MGLLineStyleLayerTests.m in Sources */, 357579891D502B06000B822E /* MGLCircleStyleLayerTests.m in Sources */, @@ -1923,6 +1943,7 @@ DA88481F1CBAFA6200AB86E3 /* MGLMultiPoint.mm in Sources */, DA88482B1CBAFA6200AB86E3 /* MGLTypes.m in Sources */, 4018B1C71CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, + 404C26E41D89B877000AA13D /* MGLTileSet.mm in Sources */, DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */, DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */, 35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */, @@ -1991,6 +2012,7 @@ DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */, DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */, DAA4E41E1CBB730400178DFB /* MGLMapCamera.mm in Sources */, + 404C26E51D89B877000AA13D /* MGLTileSet.mm in Sources */, 4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */, 35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */, diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h index 24925d169c..535e00e01e 100644 --- a/platform/ios/src/Mapbox.h +++ b/platform/ios/src/Mapbox.h @@ -56,3 +56,4 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[]; #import "NSValue+MGLStyleAttributeAdditions.h" #import "NSString+MGLStyleAttributeAdditions.h" #import "NSArray+MGLStyleAttributeAdditions.h" +#import "MGLTileSet.h" diff --git a/platform/ios/test/MGLTileSetTests.mm b/platform/ios/test/MGLTileSetTests.mm new file mode 100644 index 0000000000..d77046928c --- /dev/null +++ b/platform/ios/test/MGLTileSetTests.mm @@ -0,0 +1,82 @@ +#import + +#import +#import "MGLTileSet_Private.h" + +#include + +@interface MGLTileSetTests : XCTestCase + +@end + +@implementation MGLTileSetTests + +- (void)testTileSet { + // a tile set that provides an mbgl tile set + MGLTileSet *tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1", + @"tile.2", + @"tile.3"]]; + mbgl::Tileset mbglTileset = [tileSet mbglTileset]; + + // has the correct URL templates + XCTAssertEqual(mbglTileset.tiles.size(), 3); + XCTAssertEqual(mbglTileset.tiles[0], "tile.1"); + XCTAssertEqual(mbglTileset.tiles[1], "tile.2"); + XCTAssertEqual(mbglTileset.tiles[2], "tile.3"); + + // has the default scheme + XCTAssertEqual(mbglTileset.scheme, mbgl::Tileset::Scheme::XYZ); + + // when the tile set has no min or max zoom level set + tileSet.minimumZoomLevel = nil; + tileSet.maximumZoomLevel = nil; + + // the mbgl object has default values for min and max zoom level + XCTAssertEqual([tileSet mbglTileset].zoomRange.min, 0); + XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 22); + + // when the tile set has min and/or max zoom level set + tileSet.minimumZoomLevel = @(1); + tileSet.maximumZoomLevel = @(2); + + // the mbgl object reflects the set values for min and max zoom level + XCTAssertEqual([tileSet mbglTileset].zoomRange.min, 1); + XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 2); + + // when the tile set has an attribution + tileSet.attribution = @"my tileset © ©️🎈"; + + // the attribution is reflected by the mbgl tileset + XCTAssertEqual([tileSet mbglTileset].attribution, tileSet.attribution.UTF8String); + + // when the scheme is changed + tileSet.scheme = MGLTileSetSchemeTMS; + + // the scheme is reflected by the mbgl tileset + XCTAssertEqual([tileSet mbglTileset].scheme , mbgl::Tileset::Scheme::TMS); + + // a tile set that provides an mbgl tile set and minimum and maximum zoom levels + tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1"] minimumZoomLevel:15 maximumZoomLevel:20]; + + // the zoom levels are reflected by the mbgl tileset + XCTAssertEqual([tileSet mbglTileset].zoomRange.min, 15); + XCTAssertEqual([tileSet mbglTileset].zoomRange.max, 20); +} + +- (void)testInvalidTileSet { + // a tile set that provides an mbgl tile set and invalid (crossed) minimum and maximum zoom levels throws an exception + XCTAssertThrowsSpecificNamed([[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1"] minimumZoomLevel:10 maximumZoomLevel:9], NSException, @"Invalid minimumZoomLevel"); + + // a tile set that provides an mbgl tile set + MGLTileSet *tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[@"tile.1"]]; + tileSet.maximumZoomLevel = @(10); + + // when the minimum zoom level is set higher than the maximum zoom level + XCTAssertThrowsSpecificNamed(tileSet.minimumZoomLevel = @(11), NSException, @"Invalid minimumZoomLevel"); + + // when the maximum zoom level is set lower than the minimum zoom level + tileSet.minimumZoomLevel = @(5); + XCTAssertThrowsSpecificNamed(tileSet.maximumZoomLevel = @(4), NSException, @"Invalid minimumZoomLevel"); +} + +@end -- cgit v1.2.1