From a174588e6ccb5c0101479c882d399a07ba96ba76 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Mon, 19 Dec 2016 11:45:00 -0800 Subject: [ios, macos] Rename base to interpolationBase (#7486) --- platform/darwin/src/MGLStyleValue.h | 32 +++++++++++++-------------- platform/darwin/src/MGLStyleValue.mm | 24 ++++++++++---------- platform/darwin/src/MGLStyleValue_Private.h | 8 +++---- platform/darwin/test/MGLStyleValueTests.swift | 4 ++-- 4 files changed, 34 insertions(+), 34 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h index ab5e76bbe3..1952e6a9e8 100644 --- a/platform/darwin/src/MGLStyleValue.h +++ b/platform/darwin/src/MGLStyleValue.h @@ -49,13 +49,13 @@ NS_ASSUME_NONNULL_BEGIN /** Creates and returns an `MGLStyleFunction` object representing a zoom level - function with an exponential base and any number of stops. + function with an exponential interpolation base and any number of stops. - @param base The exponential base of the interpolation curve. + @param interpolationBase The exponential base of the interpolation curve. @param stops A dictionary associating zoom levels with style values. - @return An `MGLStyleFunction` object with the given base and stops. + @return An `MGLStyleFunction` object with the given interpolation base and stops. */ -+ (instancetype)valueWithBase:(CGFloat)base stops:(NSDictionary *> *)stops; ++ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *> *)stops; @end @@ -126,38 +126,38 @@ NS_ASSUME_NONNULL_BEGIN /** Creates and returns an `MGLStyleFunction` object representing a zoom level - function with an exponential base and any number of stops. + function with an exponential interpolation base and any number of stops. - @param base The exponential base of the interpolation curve. + @param interpolationBase The exponential base of the interpolation curve. @param stops A dictionary associating zoom levels with style values. - @return An `MGLStyleFunction` object with the given base and stops. + @return An `MGLStyleFunction` object with the given interpolation base and stops. */ -+ (instancetype)functionWithBase:(CGFloat)base stops:(NSDictionary *> *)stops; ++ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *> *)stops; #pragma mark Initializing a Style Function /** Returns an `MGLStyleFunction` object representing a zoom level function with an - exponential base and any number of stops. + exponential interpolation base and any number of stops. - @param base The exponential base of the interpolation curve. + @param interpolationBase The exponential base of the interpolation curve. @param stops A dictionary associating zoom levels with style values. - @return An `MGLStyleFunction` object with the given base and stops. + @return An `MGLStyleFunction` object with the given interpolation base and stops. */ -- (instancetype)initWithBase:(CGFloat)base stops:(NSDictionary *> *)stops NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *> *)stops NS_DESIGNATED_INITIALIZER; #pragma mark Accessing the Parameters of a Function /** - The exponential base of the function’s interpolation curve. + The exponential interpolation base of the function’s interpolation curve. - The exponential base controls the rate at which the function’s output values + The exponential interpolation base controls the rate at which the function’s output values increase. A value of 1 causes the function to increase linearly by zoom level. - A higher exponential base causes the function’s output values to vary + A higher exponential interpolation base causes the function’s output values to vary exponentially, increasing more rapidly towards the high end of the function’s range. The default value of this property is 1, for a linear curve. */ -@property (nonatomic) CGFloat base; +@property (nonatomic) CGFloat interpolationBase; /** A dictionary associating zoom levels with style values. diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm index 6ced819cd1..9e77114378 100644 --- a/platform/darwin/src/MGLStyleValue.mm +++ b/platform/darwin/src/MGLStyleValue.mm @@ -6,8 +6,8 @@ return [MGLStyleConstantValue valueWithRawValue:rawValue]; } -+ (instancetype)valueWithBase:(CGFloat)base stops:(NSDictionary *)stops { - return [MGLStyleFunction functionWithBase:base stops:stops]; ++ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops { + return [MGLStyleFunction functionWithInterpolationBase:interpolationBase stops:stops]; } + (instancetype)valueWithStops:(NSDictionary *)stops { @@ -49,44 +49,44 @@ @implementation MGLStyleFunction -+ (instancetype)functionWithBase:(CGFloat)base stops:(NSDictionary *)stops { - return [[self alloc] initWithBase:base stops:stops]; ++ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops { + return [[self alloc] initWithInterpolationBase:interpolationBase stops:stops]; } + (instancetype)functionWithStops:(NSDictionary *)stops { - return [[self alloc] initWithBase:1 stops:stops]; + return [[self alloc] initWithInterpolationBase:1 stops:stops]; } - (instancetype)init { - return [self initWithBase:1 stops:@{}]; + return [self initWithInterpolationBase:1 stops:@{}]; } -- (instancetype)initWithBase:(CGFloat)base stops:(NSDictionary *)stops { +- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops { if (self = [super init]) { if (!stops.count) { [NSException raise:NSInvalidArgumentException format:@"%@ requires at least one stop.", self]; } - _base = base; + _interpolationBase = interpolationBase; _stops = stops; } return self; } - (NSString *)description { - return [NSString stringWithFormat:@"<%@: %p, base = %f; stops = %@>", + return [NSString stringWithFormat:@"<%@: %p, interpolationBase = %f; stops = %@>", NSStringFromClass([self class]), (void *)self, - self.base, + self.interpolationBase, self.stops]; } - (BOOL)isEqual:(MGLStyleFunction *)other { - return ([other isKindOfClass:[self class]] && other.base == self.base + return ([other isKindOfClass:[self class]] && other.interpolationBase == self.interpolationBase && [other.stops isEqualToDictionary:self.stops]); } - (NSUInteger)hash { - return self.base + self.stops.hash; + return self.interpolationBase + self.stops.hash; } @end diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h index 492ce20f1a..e35c0d8008 100644 --- a/platform/darwin/src/MGLStyleValue_Private.h +++ b/platform/darwin/src/MGLStyleValue_Private.h @@ -42,7 +42,7 @@ public: for (const auto &mbglStop : mbglStops) { stops[@(mbglStop.first)] = toEnumStyleConstantValue<>(mbglStop.second); } - return [MGLStyleFunction functionWithBase:mbglValue.asFunction().getBase() stops:stops]; + return [MGLStyleFunction functionWithInterpolationBase:mbglValue.asFunction().getBase() stops:stops]; } else { return nil; } @@ -62,7 +62,7 @@ public: NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant"); mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant()); }]; - return mbgl::style::Function({{mbglStops}}, function.base); + return mbgl::style::Function({{mbglStops}}, function.interpolationBase); } else if (value) { [NSException raise:@"MGLAbstractClassException" format: @"The style value %@ cannot be applied to the style. " @@ -92,7 +92,7 @@ public: NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant"); mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant()); }]; - return mbgl::style::Function({{mbglStops}}, function.base); + return mbgl::style::Function({{mbglStops}}, function.interpolationBase); } else if (value) { [NSException raise:@"MGLAbstractClassException" format: @"The style value %@ cannot be applied to the style. " @@ -118,7 +118,7 @@ private: auto rawValue = toMGLRawStyleValue(mbglStop.second); stops[@(mbglStop.first)] = [MGLStyleValue valueWithRawValue:rawValue]; } - return [MGLStyleFunction functionWithBase:mbglFunction.getBase() stops:stops]; + return [MGLStyleFunction functionWithInterpolationBase:mbglFunction.getBase() stops:stops]; } template (base: 1, stops: stops) - XCTAssertEqual((symbolStyleLayer.iconAllowsOverlap as! MGLStyleFunction), MGLStyleFunction(base: 1, stops: stops)) + symbolStyleLayer.iconAllowsOverlap = MGLStyleFunction(interpolationBase: 1, stops: stops) + XCTAssertEqual((symbolStyleLayer.iconAllowsOverlap as! MGLStyleFunction), MGLStyleFunction(interpolationBase: 1, stops: stops)) } } -- cgit v1.2.1 From 1254bcdb4006d87fefedfc5020b3dc7d3cd0e544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 20 Dec 2016 16:11:05 -0800 Subject: [ios, macos] Update and reformat documentation for runtime styling (#7475) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [ios, macos] Optimized changelog for runtime styling Changelog entries related to style JSON now lead off with the analogous portion of the runtime styling API. * [ios, macos] Autolink cross-class property references in docs jazzy can autolink `Class.property` references in documentation comments. * [ios, macos] Removed extra blank lines * [ios, macos] Corrected typo in MGLMultiPoint docs * [ios, macos] Rewrote shape and feature docs Rewrote documentation about MGLShape, its subclasses, and MGLFeature to emphasize runtime styling uses over annotation uses, associate each type with real-world concepts, cross-reference related style layer classes, and cross-reference related or easily confused shape classes. Links to the GeoJSON specification have been updated to RFC 7946. * [ios, macos] Expanded style layer docs With this change, documentation about style layer classes is nominally based on the documentation in the style specification. However, all the existing layer types’ documentation has been overridden to explain what the layer looks like, relate the layer to a real-world concept, and cross-reference related geometry classes. This change also corrects the description of MGLBackgroundStyleLayer, which erroneously stated that the identifier must be “background”, whereas that only happens to be true by default for Studio template styles. * [ios, macos] Wrap style layer docs * [ios, macos] Removed unused code * [ios, macos] Corrected symbol references in docs * [ios, macos] Corrected typo in abstract class exception --- platform/darwin/scripts/generate-style-code.js | 35 +- .../darwin/scripts/style-spec-overrides-v8.json | 24 + platform/darwin/src/MGLAttributionInfo.h | 2 +- platform/darwin/src/MGLBackgroundStyleLayer.h | 42 +- platform/darwin/src/MGLCircleStyleLayer.h | 73 ++- platform/darwin/src/MGLFeature.h | 135 +++-- platform/darwin/src/MGLFillStyleLayer.h | 79 ++- platform/darwin/src/MGLLineStyleLayer.h | 159 ++++-- platform/darwin/src/MGLMultiPoint.h | 19 +- platform/darwin/src/MGLOfflinePack.h | 4 +- platform/darwin/src/MGLOfflineStorage.h | 3 +- platform/darwin/src/MGLOpenGLStyleLayer.mm | 17 +- platform/darwin/src/MGLOverlay.h | 5 +- platform/darwin/src/MGLPointAnnotation.h | 32 +- platform/darwin/src/MGLPointCollection.h | 27 +- platform/darwin/src/MGLPolygon.h | 58 +- platform/darwin/src/MGLPolyline.h | 58 +- platform/darwin/src/MGLRasterStyleLayer.h | 73 ++- platform/darwin/src/MGLShape.h | 41 +- platform/darwin/src/MGLShapeCollection.h | 24 +- platform/darwin/src/MGLStyle.h | 2 +- platform/darwin/src/MGLStyleLayer.h.ejs | 61 +- platform/darwin/src/MGLSymbolStyleLayer.h | 627 ++++++++++++++------- platform/darwin/src/MGLVectorStyleLayer.m | 4 +- platform/ios/CHANGELOG.md | 10 +- platform/macos/CHANGELOG.md | 6 +- platform/macos/src/MGLMapViewDelegate.h | 2 +- 27 files changed, 1137 insertions(+), 485 deletions(-) (limited to 'platform') diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 9e79d0a321..46f55c889c 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -46,6 +46,15 @@ _.forOwn(cocoaConventions, function (properties, kind) { }) }); +String.prototype.wrap = function (cols, indent) { + let wrapRe = new RegExp(`(.{1,${cols - indent}})(?: +|\n|$)`, "gm"); + return this.replace(wrapRe, "$1\n").replace(/\s+$/, "").indent(indent); +}; + +String.prototype.indent = function (cols) { + return this.replace(/^|\n/g, "$&" + " ".repeat(cols)); +}; + global.camelize = function (str) { return str.replace(/(?:^|-)(.)/g, function (_, x) { return x.toUpperCase(); @@ -126,7 +135,7 @@ global.testHelperMessage = function (property, layerType, isFunction) { } }; -global.propertyDoc = function (propertyName, property, layerType) { +global.propertyDoc = function (propertyName, property, layerType, kind) { // Match references to other property names & values. // Requires the format 'When `foo` is set to `bar`,'. let doc = property.doc.replace(/`([^`]+?)` is set to `([^`]+?)`/g, function (m, peerPropertyName, propertyValue, offset, str) { @@ -157,11 +166,24 @@ global.propertyDoc = function (propertyName, property, layerType) { if (!property.units.match(/s$/)) { property.units += 's'; } - doc += ` - - This property is measured in ${property.units}.`; + doc += `\n\nThis property is measured in ${property.units}.`; + } + doc = doc.replace(/(p)ixel/gi, '$1oint').replace(/(\d)px\b/g, '$1pt'); + if (kind !== 'enum') { + if ('default' in property) { + doc += `\n\nThe default value of this property is ${propertyDefault(property, layerType)}.`; + if (!property.required) { + doc += ' Set this property to `nil` to reset it to the default value.'; + } + } + if ('requires' in property) { + doc += '\n\n' + propertyReqs(property, spec[`${kind}_${layerType}`], layerType); + } + if ('original' in property) { + doc += `\n\nThis attribute corresponds to the ${property.original} layout property in the Mapbox Style Specification.`; + } } - return doc.replace(/(p)ixel/gi, '$1oint').replace(/(\d)px\b/g, '$1pt'); + return doc; }; global.propertyReqs = function (property, propertiesByName, type) { @@ -365,11 +387,10 @@ const layers = Object.keys(spec.layer.type.values).map((type) => { }, []); return { + doc: spec.layer.type.values[type].doc, type: type, layoutProperties: _.sortBy(layoutProperties, ['name']), paintProperties: _.sortBy(paintProperties, ['name']), - layoutPropertiesByName: spec[`layout_${type}`], - paintPropertiesByName: spec[`paint_${type}`], }; }); diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json index cfda85b7fb..f42c059f59 100644 --- a/platform/darwin/scripts/style-spec-overrides-v8.json +++ b/platform/darwin/scripts/style-spec-overrides-v8.json @@ -1,4 +1,28 @@ { + "layer": { + "type": { + "values": { + "fill": { + "doc": "An `MGLFillStyleLayer` is a style layer that renders one or more filled (and optionally stroked) polygons on the map.\n\nUse a fill style layer to configure the visual appearance of polygon or multipolygon features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object." + }, + "line": { + "doc": "An `MGLLineStyleLayer` is a style layer that renders one or more stroked polylines on the map.\n\nUse a line style layer to configure the visual appearance of polyline or multipolyline features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or `MGLMultiPolylineFeature` instances in an `MGLShapeSource` object." + }, + "symbol": { + "doc": "An `MGLSymbolStyleLayer` is a style layer that renders icon and text labels at points or along lines on the map.\n\nUse a symbol style layer to configure the visual appearance of labels for features in vector tiles loaded by an `MGLVectorSource` object or `MGLShape` or `MGLFeature` instances in an `MGLShapeSource` object." + }, + "circle": { + "doc": "An `MGLCircleStyleLayer` is a style layer that renders one or more filled circles on the map.\n\nUse a circle style layer to configure the visual appearance of point or point collection features in vector tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` object.\n\nA circle style layer renders circles whose radii are measured in screen units. To display circles on the map whose radii correspond to real-world distances, use many-sided regular polygons and configure their appearance using an `MGLFillStyleLayer` object." + }, + "raster": { + "doc": "An `MGLRasterStyleLayer` is a style layer that renders raster tiles on the map.\n\nUse a raster style layer to configure the color parameters of raster tiles loaded by an `MGLRasterSource` object. For example, you could use a raster style layer to render Mapbox Satellite imagery, a raster tile set uploaded to Mapbox Studio, or a raster map authored in TileMill, the classic Mapbox Editor, or Mapbox Studio Classic." + }, + "background": { + "doc": "An `MGLBackgroundStyleLayer` is a style layer that covers the entire map. Use a background style layer to configure a color or pattern to show below all other map content. If the style’s other layers use the Mapbox Streets source, the background style layer is responsible for drawing land, whereas the oceans and other bodies of water are drawn by `MGLFillStyleLayer` objects.\n\nA background style layer is typically the bottommost layer in a style, because it covers the entire map and can occlude any layers below it. You can therefore access it by getting the last item in the `MGLStyle.layers` array.\n\nIf the background style layer is transparent or omitted from the style, any portion of the map view that does not show another style layer is transparent." + } + } + } + }, "layout_symbol": { "icon-text-fit-padding": { "doc": "Size of the additional area added to dimensions determined by `icon-text-fit`." diff --git a/platform/darwin/src/MGLAttributionInfo.h b/platform/darwin/src/MGLAttributionInfo.h index 7395e3f346..3c9df47912 100644 --- a/platform/darwin/src/MGLAttributionInfo.h +++ b/platform/darwin/src/MGLAttributionInfo.h @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN coordinate and zoom level. @param centerCoordinate The map’s center coordinate. - @param zoomLevel The map’s zoom level. See `MGLMapView`’s `zoomLevel` property + @param zoomLevel The map’s zoom level. See the `MGLMapView.zoomLevel` property for more information. @return A modified URL containing a fragment that points to the specified viewport. If the `feedbackLink` property is set to `NO`, this method returns diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.h b/platform/darwin/src/MGLBackgroundStyleLayer.h index 656e104bbb..bcaf21a8d4 100644 --- a/platform/darwin/src/MGLBackgroundStyleLayer.h +++ b/platform/darwin/src/MGLBackgroundStyleLayer.h @@ -7,10 +7,18 @@ NS_ASSUME_NONNULL_BEGIN /** - A map style's background layer is the bottommost layer and is used to style a color - or pattern to show below all other map features. You can query an `MGLMapView` for its - `style` and obtain the background layer using the `-[MGLStyle layerWithIdentifier:]` - method and passing `background` for the identifier. + An `MGLBackgroundStyleLayer` is a style layer that covers the entire map. Use a + background style layer to configure a color or pattern to show below all other + map content. If the style’s other layers use the Mapbox Streets source, the + background style layer is responsible for drawing land, whereas the oceans and + other bodies of water are drawn by `MGLFillStyleLayer` objects. + + A background style layer is typically the bottommost layer in a style, because + it covers the entire map and can occlude any layers below it. You can therefore + access it by getting the last item in the `MGLStyle.layers` array. + + If the background style layer is transparent or omitted from the style, any + portion of the map view that does not show another style layer is transparent. */ @interface MGLBackgroundStyleLayer : MGLStyleLayer @@ -22,18 +30,24 @@ NS_ASSUME_NONNULL_BEGIN /** The color with which the background will be drawn. - The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `backgroundPattern` is set to `nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `backgroundPattern` is set to + `nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *backgroundColor; #else /** The color with which the background will be drawn. - The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `backgroundPattern` is set to `nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `backgroundPattern` is set to + `nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *backgroundColor; #endif @@ -41,12 +55,16 @@ NS_ASSUME_NONNULL_BEGIN /** The opacity at which the background will be drawn. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *backgroundOpacity; /** - Name of image in style images to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). + Name of image in style images to use for drawing an image background. For + seamless patterns, image width and height must be a factor of two (2, 4, 8, + ..., 512). */ @property (nonatomic, null_resettable) MGLStyleValue *backgroundPattern; diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h index 2d88a664ba..ddea62e5be 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.h +++ b/platform/darwin/src/MGLCircleStyleLayer.h @@ -9,7 +9,8 @@ NS_ASSUME_NONNULL_BEGIN /** Controls the scaling behavior of the circle when the map is pitched. - Values of this type are used in the `circlePitchScale` property of `MGLCircleStyleLayer`. + Values of this type are used in the `MGLCircleStyleLayer.circlePitchScale` + property. */ typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) { /** @@ -25,7 +26,8 @@ typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) { /** Controls the translation reference point. - Values of this type are used in the `circleTranslateAnchor` property of `MGLCircleStyleLayer`. + Values of this type are used in the `MGLCircleStyleLayer.circleTranslateAnchor` + property. */ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) { /** @@ -39,19 +41,36 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) { }; /** - A circle layer which allows customization of styling properties at runtime. You may - instantiate a new circle layer to add to a map style or you may query an - `MGLMapView` for its `style` and obtain existing layers using the - `-[MGLStyle layerWithIdentifier:]` method. + An `MGLCircleStyleLayer` is a style layer that renders one or more filled + circles on the map. + + Use a circle style layer to configure the visual appearance of point or point + collection features in vector tiles loaded by an `MGLVectorSource` object or + `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or + `MGLPointCollectionFeature` instances in an `MGLShapeSource` object. + + A circle style layer renders circles whose radii are measured in screen units. + To display circles on the map whose radii correspond to real-world distances, + use many-sided regular polygons and configure their appearance using an + `MGLFillStyleLayer` object. + + You can access an existing circle style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new circle style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. */ @interface MGLCircleStyleLayer : MGLVectorStyleLayer #pragma mark - Accessing the Paint Attributes /** - Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity. + Amount to blur the circle. 1 blurs the circle such that only the centerpoint is + full opacity. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *circleBlur; @@ -59,14 +78,18 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) { /** The fill color of the circle. - The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. */ @property (nonatomic, null_resettable) MGLStyleValue *circleColor; #else /** The fill color of the circle. - The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. */ @property (nonatomic, null_resettable) MGLStyleValue *circleColor; #endif @@ -74,41 +97,53 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) { /** The opacity at which the circle will be drawn. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *circleOpacity; /** Controls the scaling behavior of the circle when the map is pitched. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLCirclePitchScaleMap`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLCirclePitchScaleMap`. Set this property to + `nil` to reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *circlePitchScale; /** Circle radius. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `5`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `5`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *circleRadius; /** The geometry's offset. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points from the left + and 0 points from the top. Set this property to `nil` to reset it to the + default value. */ @property (nonatomic, null_resettable) MGLStyleValue *circleTranslate; /** Controls the translation reference point. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLCircleTranslateAnchorMap`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `circleTranslate` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLCircleTranslateAnchorMap`. Set this property to + `nil` to reset it to the default value. + + This property is only applied to the style if `circleTranslate` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *circleTranslateAnchor; diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h index ed4ff627b9..e05c37720d 100644 --- a/platform/darwin/src/MGLFeature.h +++ b/platform/darwin/src/MGLFeature.h @@ -10,30 +10,41 @@ NS_ASSUME_NONNULL_BEGIN /** The `MGLFeature` protocol is used to provide details about geographic features - contained in a map view’s - tile sources. - Each concrete subclass of `MGLShape` in turn has a subclass that conforms to - this protocol. - - Typically, you do not create feature objects yourself but rather obtain them - using `-[MGLMapView visibleFeaturesAtPoint:]` and related methods. Each feature - object associates a shape with an identifier and attributes as specified by the - source. Like ordinary `MGLAnnotation` objects, some kinds of `MGLFeature` - objects can also be added to a map view using an `MGLShapeSource` or - `-[MGLMapView addAnnotations:]` and related methods. + contained in an `MGLShapeSource` or `MGLVectorSource` object. Each concrete + subclass of `MGLShape` in turn has a subclass that conforms to this protocol. A + feature object associates a shape with an optional identifier and attributes. + + You can add custom data to display on the map by creating feature objects and + adding them to an `MGLShapeSource` using the + `-[MGLShapeSource initWithIdentifier:shape:options:]` method or + `MGLShapeSource.shape` property. Similarly, you can add `MGLPointFeature`, + `MGLPolylineFeature`, and `MGLPolygonFeature` objects to the map as annotations + using `-[MGLMapView addAnnotations:]` and related methods. + + In addition to adding data to the map, you can also extract data from the map: + `-[MGLMapView visibleFeaturesAtPoint:]` and related methods return feature + objects that correspond to features in the source. This enables you to inspect + the properties of features in vector tiles loaded by `MGLVectorSource` objects. + You also reuse these feature objects as overlay annotations. */ @protocol MGLFeature /** - An object that uniquely identifies the feature in its containing - tile source. + An object that uniquely identifies the feature in its containing content + source. - The identifier corresponds to the + You can configure an `MGLVectorStyleLayer` object to include or exclude a + specific feature in an `MGLShapeSource` or `MGLVectorSource`. In the + `MGLVectorStyleLayer.predicate` property, compare the special `$id` attribute + to the feature’s identifier. + + In vector tiles loaded by `MGLVectorSource` objects, the identifier corresponds + to the feature identifier - (`id`) in the tile source. If the source does not specify the feature’s - identifier, the value of this property is `nil`. If specified, the identifier - may be an integer, floating-point number, or string. These data types are - mapped to instances of the following Foundation classes: + (`id`). If the source does not specify the feature’s identifier, the value of + this property is `nil`. If specified, the identifier may be an integer, + floating-point number, or string. These data types are mapped to instances of + the following Foundation classes: @@ -49,22 +60,40 @@ NS_ASSUME_NONNULL_BEGIN For details about the identifiers used in most Mapbox-provided styles, consult the Mapbox Streets - layer reference. Note that while it is possible to change this value on feature - instances obtained from `-[MGLMapView visibleFeaturesAtPoint:]` and related - methods, there will be no effect on the map. Setting this value can be useful - when the feature instance is used to initialize an `MGLShapeSource` and that - source is added to the map and styled. + layer reference. + + The identifier should be set before adding the feature to an `MGLShapeSource` + object; setting it afterwards has no effect on the map’s contents. While it is + possible to change this value on feature instances obtained from + `-[MGLMapView visibleFeaturesAtPoint:]` and related methods, doing so likewise + has no effect on the map’s contents. */ @property (nonatomic, copy, nullable) id identifier; /** - A dictionary of attributes for this feature specified by the - tile source. + A dictionary of attributes for this feature. + + You can configure an `MGLVectorStyleLayer` object to include or exclude a + specific feature in an `MGLShapeSource` or `MGLVectorSource`. In the + `MGLVectorStyleLayer.predicate` property, compare a key of the attribute + dictionary to the value you want to include. For example, if you want an + `MGLLineStyleLayer` object to display only important features, you might assign + a value above 50 to the important features’ `importance` attribute, then set + `MGLVectorStyleLayer.predicate` to an `NSPredicate` with the format + `importance > 50`. - The keys and values of this dictionary are determined by the tile source. In - the tile source, each attribute name is a string, while each attribute value - may be a null value, Boolean value, integer, floating-point number, or string. - These data types are mapped to instances of the following Foundation classes: + You can also configure some attributes of an `MGLSymbolStyleLayer` object to + include the value of an attribute in this dictionary whenever it renders this + feature. For example, to label features in an `MGLShapeSource` object by their + names, you can assign a `name` attribute to each of the source’s features, then + set `MGLSymbolStyleLayer.textField` to an `MGLStyleValue` object containing the + string `{name}`. + + In vector tiles loaded by `MGLVectorSource` objects, the keys and values of + each feature’s attribute dictionary are determined by the source. Each + attribute name is a string, while each attribute value may be a null value, + Boolean value, integer, floating-point number, or string. These data types are + mapped to instances of the following Foundation classes:
@@ -84,7 +113,9 @@ NS_ASSUME_NONNULL_BEGIN Mapbox Streets and Mapbox Terrain - layer references. Note that while it is possible to change this value on feature + layer references. + + Note that while it is possible to change this value on feature instances obtained from `-[MGLMapView visibleFeaturesAtPoint:]` and related methods, there will be no effect on the map. Setting this value can be useful when the feature instance is used to initialize an `MGLShapeSource` and that @@ -114,50 +145,66 @@ NS_ASSUME_NONNULL_BEGIN @end /** - The `MGLPointFeature` class represents a point in a - tile source. + An `MGLPointFeature` object associates a point shape with an optional + identifier and attributes. */ @interface MGLPointFeature : MGLPointAnnotation @end /** - The `MGLPolylineFeature` class represents a polyline in a - tile source. + An `MGLPolylineFeature` object associates a polyline shape with an optional + identifier and attributes. + + A polyline feature is known as a + LineString + feature in GeoJSON. */ @interface MGLPolylineFeature : MGLPolyline @end /** - The `MGLPolygonFeature` class represents a polygon in a - tile source. + An `MGLPolygonFeature` object associates a polygon shape with an optional + identifier and attributes. */ @interface MGLPolygonFeature : MGLPolygon @end /** - The `MGLPointCollectionFeature` class represents a multipoint in a - tile source. + An `MGLPointCollectionFeature` object associates a point collection with an + optional identifier and attributes. + + A point collection feature is known as a + MultiPoint + feature in GeoJSON. */ @interface MGLPointCollectionFeature : MGLPointCollection @end /** - The `MGLMultiPolylineFeature` class represents a multipolyline in a - tile source. + An `MGLMultiPolylineFeature` object associates a multipolyline shape with an + optional identifier and attributes. + + A multipolyline feature is known as a + MultiLineString + feature in GeoJSON. */ @interface MGLMultiPolylineFeature : MGLMultiPolyline @end /** - The `MGLMultiPolygonFeature` class represents a multipolygon in a - tile source. + An `MGLMultiPolygonFeature` object associates a multipolygon shape with an + optional identifier and attributes. */ @interface MGLMultiPolygonFeature : MGLMultiPolygon @end /** - The `MGLShapeCollectionFeature` class represents a shape collection in a - tile source. + An `MGLShapeCollectionFeature` object associates a shape collection with an + optional identifier and attributes. + + A shape collection feature is known as a + feature collection + in GeoJSON. */ @interface MGLShapeCollectionFeature : MGLShapeCollection diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h index cf8c18b5c2..01f1b17f97 100644 --- a/platform/darwin/src/MGLFillStyleLayer.h +++ b/platform/darwin/src/MGLFillStyleLayer.h @@ -9,7 +9,8 @@ NS_ASSUME_NONNULL_BEGIN /** Controls the translation reference point. - Values of this type are used in the `fillTranslateAnchor` property of `MGLFillStyleLayer`. + Values of this type are used in the `MGLFillStyleLayer.fillTranslateAnchor` + property. */ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) { /** @@ -23,10 +24,19 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) { }; /** - A fill layer which allows customization of styling properties at runtime. You may - instantiate a new fill layer to add to a map style or you may query an - `MGLMapView` for its `style` and obtain existing layers using the - `-[MGLStyle layerWithIdentifier:]` method. + An `MGLFillStyleLayer` is a style layer that renders one or more filled (and + optionally stroked) polygons on the map. + + Use a fill style layer to configure the visual appearance of polygon or + multipolygon features in vector tiles loaded by an `MGLVectorSource` object or + `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or + `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object. + + You can access an existing fill style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new fill style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. */ @interface MGLFillStyleLayer : MGLVectorStyleLayer @@ -35,69 +45,90 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) { /** Whether or not the fill should be antialiased. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `YES`. Set this property to `nil` to reset it to + the default value. - This attribute corresponds to the fill-antialias paint property in the Mapbox Style Specification. + This attribute corresponds to the fill-antialias + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable, getter=isFillAntialiased) MGLStyleValue *fillAntialiased; - @property (nonatomic, null_resettable) MGLStyleValue *fillAntialias __attribute__((unavailable("Use fillAntialiased instead."))); #if TARGET_OS_IPHONE /** The color of the filled part of this layer. - The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `fillPattern` is set to `nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `fillPattern` is set to `nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *fillColor; #else /** The color of the filled part of this layer. - The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `fillPattern` is set to `nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `fillPattern` is set to `nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *fillColor; #endif /** - The opacity of the entire fill layer. In contrast to the `fillColor`, this value will also affect the 1pt stroke around the fill, if the stroke is used. + The opacity of the entire fill layer. In contrast to the `fillColor`, this + value will also affect the 1pt stroke around the fill, if the stroke is used. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *fillOpacity; /** The outline color of the fill. Matches the value of `fillColor` if unspecified. - - This property is only applied to the style if `fillPattern` is set to `nil`, and `fillAntialiased` is set to an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Otherwise, it is ignored. + + This property is only applied to the style if `fillPattern` is set to `nil`, + and `fillAntialiased` is set to an `MGLStyleValue` object containing an + `NSNumber` object containing `YES`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *fillOutlineColor; /** - Name of image in sprite to use for drawing image fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512). + Name of image in sprite to use for drawing image fills. For seamless patterns, + image width and height must be a factor of two (2, 4, 8, ..., 512). */ @property (nonatomic, null_resettable) MGLStyleValue *fillPattern; /** The geometry's offset. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points from the left + and 0 points from the top. Set this property to `nil` to reset it to the + default value. */ @property (nonatomic, null_resettable) MGLStyleValue *fillTranslate; /** Controls the translation reference point. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLFillTranslateAnchorMap`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `fillTranslate` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLFillTranslateAnchorMap`. Set this property to + `nil` to reset it to the default value. + + This property is only applied to the style if `fillTranslate` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *fillTranslateAnchor; diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index c47c7d5166..c0f2eb322b 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -9,19 +9,24 @@ NS_ASSUME_NONNULL_BEGIN /** The display of line endings. - Values of this type are used in the `lineCap` property of `MGLLineStyleLayer`. + Values of this type are used in the `MGLLineStyleLayer.lineCap` + property. */ typedef NS_ENUM(NSUInteger, MGLLineCap) { /** - A cap with a squared-off end which is drawn to the exact endpoint of the line. + A cap with a squared-off end which is drawn to the exact endpoint of the + line. */ MGLLineCapButt, /** - A cap with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's width and centered on the endpoint of the line. + A cap with a rounded end which is drawn beyond the endpoint of the line at + a radius of one-half of the line's width and centered on the endpoint of + the line. */ MGLLineCapRound, /** - A cap with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the line's width. + A cap with a squared-off end which is drawn beyond the endpoint of the line + at a distance of one-half of the line's width. */ MGLLineCapSquare, }; @@ -29,19 +34,24 @@ typedef NS_ENUM(NSUInteger, MGLLineCap) { /** The display of lines when joining. - Values of this type are used in the `lineJoin` property of `MGLLineStyleLayer`. + Values of this type are used in the `MGLLineStyleLayer.lineJoin` + property. */ typedef NS_ENUM(NSUInteger, MGLLineJoin) { /** - A join with a squared-off end which is drawn beyond the endpoint of the line at a distance of one-half of the line's width. + A join with a squared-off end which is drawn beyond the endpoint of the + line at a distance of one-half of the line's width. */ MGLLineJoinBevel, /** - A join with a rounded end which is drawn beyond the endpoint of the line at a radius of one-half of the line's width and centered on the endpoint of the line. + A join with a rounded end which is drawn beyond the endpoint of the line at + a radius of one-half of the line's width and centered on the endpoint of + the line. */ MGLLineJoinRound, /** - A join with a sharp, angled corner which is drawn with the outer sides beyond the endpoint of the path until they meet. + A join with a sharp, angled corner which is drawn with the outer sides + beyond the endpoint of the path until they meet. */ MGLLineJoinMiter, }; @@ -49,7 +59,8 @@ typedef NS_ENUM(NSUInteger, MGLLineJoin) { /** Controls the translation reference point. - Values of this type are used in the `lineTranslateAnchor` property of `MGLLineStyleLayer`. + Values of this type are used in the `MGLLineStyleLayer.lineTranslateAnchor` + property. */ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { /** @@ -63,10 +74,19 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { }; /** - A line layer which allows customization of styling properties at runtime. You may - instantiate a new line layer to add to a map style or you may query an - `MGLMapView` for its `style` and obtain existing layers using the - `-[MGLStyle layerWithIdentifier:]` method. + An `MGLLineStyleLayer` is a style layer that renders one or more stroked + polylines on the map. + + Use a line style layer to configure the visual appearance of polyline or + multipolyline features in vector tiles loaded by an `MGLVectorSource` object or + `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or + `MGLMultiPolylineFeature` instances in an `MGLShapeSource` object. + + You can access an existing line style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new line style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. */ @interface MGLLineStyleLayer : MGLVectorStyleLayer @@ -75,32 +95,44 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { /** The display of line endings. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineCapButt`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLLineCapButt`. Set this property to `nil` to + reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineCap; /** The display of lines when joining. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineJoinMiter`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLLineJoinMiter`. Set this property to `nil` to + reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineJoin; /** Used to automatically convert miter joins to bevel joins for sharp angles. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `2`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `lineJoin` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineJoinMiter`. Otherwise, it is ignored. + This property is only applied to the style if `lineJoin` is set to an + `MGLStyleValue` object containing an `NSValue` object containing + `MGLLineJoinMiter`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *lineMiterLimit; /** Used to automatically convert round joins to miter joins for shallow angles. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1.05`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1.05`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `lineJoin` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineJoinRound`. Otherwise, it is ignored. + This property is only applied to the style if `lineJoin` is set to an + `MGLStyleValue` object containing an `NSValue` object containing + `MGLLineJoinRound`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *lineRoundLimit; @@ -108,10 +140,12 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { /** Blur applied to the line, in points. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineBlur; @@ -119,90 +153,119 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { /** The color with which the line will be drawn. - The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `linePattern` is set to `nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `linePattern` is set to `nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *lineColor; #else /** The color with which the line will be drawn. - The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `linePattern` is set to `nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `linePattern` is set to `nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *lineColor; #endif /** - Specifies the lengths of the alternating dashes and gaps that form the dash pattern. The lengths are later scaled by the line width. To convert a dash length to points, multiply the length by the current line width. - + Specifies the lengths of the alternating dashes and gaps that form the dash + pattern. The lengths are later scaled by the line width. To convert a dash + length to points, multiply the length by the current line width. + This property is measured in line widths. - - This property is only applied to the style if `linePattern` is set to `nil`. Otherwise, it is ignored. - This attribute corresponds to the line-dasharray paint property in the Mapbox Style Specification. + This property is only applied to the style if `linePattern` is set to `nil`. + Otherwise, it is ignored. + + This attribute corresponds to the line-dasharray + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *> *lineDashPattern; - @property (nonatomic, null_resettable) MGLStyleValue *> *lineDasharray __attribute__((unavailable("Use lineDashPattern instead."))); /** - Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap. - + Draws a line casing outside of a line's actual path. Value indicates the width + of the inner gap. + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineGapWidth; /** - The line's offset. For linear features, a positive value offsets the line to the right, relative to the direction of the line, and a negative value to the left. For polygon features, a positive value results in an inset, and a negative value results in an outset. - + The line's offset. For linear features, a positive value offsets the line to + the right, relative to the direction of the line, and a negative value to the + left. For polygon features, a positive value results in an inset, and a + negative value results in an outset. + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineOffset; /** The opacity at which the line will be drawn. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineOpacity; /** - Name of image in style images to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512). + Name of image in style images to use for drawing image lines. For seamless + patterns, image width must be a factor of two (2, 4, 8, ..., 512). */ @property (nonatomic, null_resettable) MGLStyleValue *linePattern; /** The geometry's offset. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points from the left + and 0 points from the top. Set this property to `nil` to reset it to the + default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineTranslate; /** Controls the translation reference point. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineTranslateAnchorMap`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `lineTranslate` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLLineTranslateAnchorMap`. Set this property to + `nil` to reset it to the default value. + + This property is only applied to the style if `lineTranslate` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *lineTranslateAnchor; /** Stroke thickness. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *lineWidth; diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h index ed40ee9cad..f083a5bec4 100644 --- a/platform/darwin/src/MGLMultiPoint.h +++ b/platform/darwin/src/MGLMultiPoint.h @@ -7,10 +7,15 @@ NS_ASSUME_NONNULL_BEGIN /** The `MGLMultiPoint` class is an abstract superclass used to define shapes - composed of multiple vertices. You should not create instances of this class - directly. Instead, you should create instances of the `MGLPolyline` or - `MGLPolygon` classes. However, you can use the method and properties of this - class to access information about the vertices of the line or polygon. + composed of multiple vertices. + + You do not create instances of this class directly. Instead, you create + instances of the `MGLPolyline` or `MGLPolygon` classes. However, you can use + the method and properties of this class to access information about the + vertices of the line or polygon. + + Do not confuse `MGLMultiPoint` with `MGLPointCollection`, which represents a + collection of related but disconnected points. */ @interface MGLMultiPoint : MGLShape @@ -55,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN the map, it is redrawn immediately. @param coords The array of coordinates to insert into the shape. The data in - this array is copied to the shape’s `coordinate` property. + this array is copied to the shape’s `coordinates` property. @param count The number of items in the `coords` array. @param index The zero-based index at which the first coordinate in `coords` will appear in the `coordinates` property. @@ -67,7 +72,7 @@ NS_ASSUME_NONNULL_BEGIN the map, it is redrawn immediately. @param coords The array of coordinates to add to the shape. The data in this - array is copied to the shape’s `coordinate` property. + array is copied to the shape’s `coordinates` property. @param count The number of items in the `coords` array. */ - (void)appendCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count; @@ -90,7 +95,7 @@ NS_ASSUME_NONNULL_BEGIN being the second vertex, and so on. The `length` field indicates the number of vertices to replace. @param coords The array of coordinates defining part of the shape. The data in - this array is copied to the shape’s `coordinate` property. + this array is copied to the shape’s `coordinates` property. */ - (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords; diff --git a/platform/darwin/src/MGLOfflinePack.h b/platform/darwin/src/MGLOfflinePack.h index a14d001d0f..a741833105 100644 --- a/platform/darwin/src/MGLOfflinePack.h +++ b/platform/darwin/src/MGLOfflinePack.h @@ -25,8 +25,8 @@ typedef NS_ENUM (NSInteger, MGLOfflinePackState) { The pack is incomplete and is not currently downloading. This is the initial state of a pack that is created using the - `-[MGLOfflinePack addPackForRegion:withContext:completionHandler:]` method, - as well as after the `-[MGLOfflinePack suspend]` method is + `-[MGLOfflineStorage addPackForRegion:withContext:completionHandler:]` + method, as well as after the `-[MGLOfflinePack suspend]` method is called. */ MGLOfflinePackStateInactive = 1, diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h index b3fb7a2d54..c58907d0d5 100644 --- a/platform/darwin/src/MGLOfflineStorage.h +++ b/platform/darwin/src/MGLOfflineStorage.h @@ -18,7 +18,8 @@ NS_ASSUME_NONNULL_BEGIN `userInfo` dictionary contains the pack’s current state in the `MGLOfflinePackStateUserInfoKey` key and details about the pack’s current progress in the `MGLOfflinePackProgressUserInfoKey` key. You may also consult - the pack’s `state` and `progress` properties, which provide the same values. + the `MGLOfflinePack.state` and `MGLOfflinePack.progress` properties, which + provide the same values. If you only need to observe changes in a particular pack’s progress, you can alternatively observe KVO change notifications to the pack’s `progress` key diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm index f109ea85b0..ac2a6abcd9 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.mm +++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm @@ -52,10 +52,19 @@ void MGLFinishCustomStyleLayer(void *context) { } /** - An `MGLOpenGLStyleLayer` is a style layer that is rendered by OpenGL code in - Objective-C blocks or Swift closures that you specify. You may initialize a new - OpenGL style layer to add to an `MGLStyle` or obtain one from an `MGLMapView`’s - current style using the `-[MGLStyle layerWithIdentifier:]` method. + An `MGLOpenGLStyleLayer` is a style layer that is rendered by OpenGL code that + you provide. + + By default, this class does nothing. You can subclass this class to provide + custom OpenGL drawing code that is run on each frame of the map. Your subclass + should override the `-didMoveToMapView:`, `-willMoveFromMapView:`, and + `-drawInMapView:withContext:` methods. + + You can access an existing OpenGL style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new OpenGL style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. @warning This API is undocumented and therefore unsupported. It may change at any time without notice. diff --git a/platform/darwin/src/MGLOverlay.h b/platform/darwin/src/MGLOverlay.h index 1066a86d1e..cc32bad1e6 100644 --- a/platform/darwin/src/MGLOverlay.h +++ b/platform/darwin/src/MGLOverlay.h @@ -9,9 +9,8 @@ NS_ASSUME_NONNULL_BEGIN /** The `MGLOverlay` protocol defines a specific type of annotation that represents both a point and an area on a map. Overlay objects are essentially data objects - that contain the geographic data needed to represent the map area. For example, - overlays can take the form of common shapes such as rectangles and circles. - They can also describe polygons and other complex shapes. + that contain the geographic data needed to represent the map area. Overlays can + take the form of a polyline or polygon. You use overlays to layer more sophisticated content on top of a map view. For example, you could use an overlay to show the boundaries of a national park or diff --git a/platform/darwin/src/MGLPointAnnotation.h b/platform/darwin/src/MGLPointAnnotation.h index b552912f97..969f8c91e7 100644 --- a/platform/darwin/src/MGLPointAnnotation.h +++ b/platform/darwin/src/MGLPointAnnotation.h @@ -6,15 +6,37 @@ NS_ASSUME_NONNULL_BEGIN /** - The `MGLPointAnnotation` class defines a concrete annotation object located at - a specified point. You can use this class, rather than define your own, in - situations where all you want to do is associate a point on the map with a - title. + An `MGLPointAnnotation` object represents a one-dimensional shape located at a + single geographical coordinate. Depending on how it is used, an + `MGLPointAnnotation` object is known as a point annotation or point shape. For + example, you could use a point shape to represent a city at low zoom levels, an + address at high zoom levels, or the location of a long press gesture. + + You can add point shapes to the map by adding them to an `MGLShapeSource` + object. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s point shapes collectively using an `MGLCircleStyleLayer` or + `MGLSymbolStyleLayer` object. + + For more interactivity, add a selectable point annotation to a map view using + the `-[MGLMapView addAnnotation:]` method. Alternatively, define your own model + class that conforms to the `MGLAnnotation` protocol. Configure a point + annotation’s appearance using + `-[MGLMapViewDelegate mapView:imageForAnnotation:]` or + `-[MGLMapViewDelegate mapView:viewForAnnotation:]` (iOS only). A point + annotation’s `MGLShape.title` and `MGLShape.subtitle` properties define the + default content of the annotation’s callout (on iOS) or popover (on macOS). + + To group multiple related points together in one shape, use an + `MGLPointCollection` or `MGLShapeCollection` object. + + A point shape is known as a + Point geometry + in GeoJSON. */ @interface MGLPointAnnotation : MGLShape /** - The coordinate point of the annotation, specified as a latitude and longitude. + The coordinate point of the shape, specified as a latitude and longitude. */ @property (nonatomic, assign) CLLocationCoordinate2D coordinate; diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h index 95af9dae5e..9e14161aed 100644 --- a/platform/darwin/src/MGLPointCollection.h +++ b/platform/darwin/src/MGLPointCollection.h @@ -5,15 +5,26 @@ #import "MGLShape.h" /** - The `MGLPointCollection` class is used to define an array of disconnected - coordinates. The points in the collection may be related but are not - connected visually in any way. + An `MGLPointCollection` object represents a shape consisting of one or more + disconnected vertices, specified as `CLLocationCoordinate2D` instances. The + points in the collection may be related but are not connected spatially. For + example, you could use a point collection to represent all the trees in an + orchard. - @note `MGLPointCollection` objects cannot be added to a map view using - `-[MGLMapView addAnnotations:]` and related methods. However, when used in a - `MGLPointCollectionFeature` to initialize a `MGLShapeSource` that is added - to the map view's style, the point collection represents as a group of distinct - annotations. + You can add point collections to the map by adding them to an `MGLShapeSource` + object. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s point collections collectively using an + `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` object. + + You cannot add an `MGLPointCollection` object directly to a map view as an + annotation. However, you can create individual `MGLPointAnnotation` objects + from the `coordinates` array and add those annotation objects to the map view + using the `-[MGLMapView addAnnotations:]` method. + + A point collection is known as a + MultiPoint + geometry in GeoJSON. Do not confuse `MGLPointCollection` with `MGLMultiPoint`, + the abstract superclass of `MGLPolyline` and `MGLPolygon`. */ @interface MGLPointCollection : MGLShape diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h index b9ec6b8399..674c006095 100644 --- a/platform/darwin/src/MGLPolygon.h +++ b/platform/darwin/src/MGLPolygon.h @@ -9,10 +9,39 @@ NS_ASSUME_NONNULL_BEGIN /** - The `MGLPolygon` class represents a shape consisting of one or more points that - define a closed polygon. The points are connected end-to-end in the order they - are provided. The first and last points are connected to each other to create - the closed shape. + An `MGLPolygon` object represents a closed shape consisting of four or more + vertices, specified as `CLLocationCoordinate2D` instances, and the edges that + connect them. For example, you could use a polygon shape to represent a + building, a lake, or an area you want to highlight. + + You can add polygon shapes to the map by adding them to an `MGLShapeSource` + object. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s polygons collectively using an `MGLFillStyleLayer` or + `MGLSymbolStyleLayer` object. + + Alternatively, you can add a polygon overlay directly to a map view using the + `-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]` method. Configure + a polygon overlay’s appearance using + `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` and + `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. + + The vertices are automatically connected in the order in which you provide + them. You should close the polygon by specifying the same + `CLLocationCoordinate2D` as the first and last vertices; otherwise, the + polygon’s fill may not cover the area you expect it to. To avoid filling the + space within the shape, give the polygon a transparent fill or use an + `MGLPolyline` object. + + A polygon may have one or more interior polygons, or holes, that you specify as + `MGLPolygon` objects with the `+polygonWithCoordinates:count:interiorPolygons:` + method. For example, if a polygon represents a lake, it could exclude an island + within the lake using an interior polygon. Interior polygons may not themselves + have interior polygons. To represent a shape that includes a polygon within a + hole or, more generally, to group multiple polygons together in one shape, use + an `MGLMultiPolygon` or `MGLShapeCollection` object. + + To make the polygon straddle the antimeridian, specify some longitudes less + than −180 degrees or greater than 180 degrees. */ @interface MGLPolygon : MGLMultiPoint @@ -55,14 +84,21 @@ NS_ASSUME_NONNULL_BEGIN @end /** - The `MGLMultiPolygon` class represents a shape consisting of one or more - polygons that do not overlap. For example, you would use an `MGLMultiPolygon` - object to represent an atoll together with an island in the atoll’s lagoon: - the atoll itself would be one `MGLPolygon` object, while the inner island would - be another. + An `MGLMultiPolygon` object represents a shape consisting of one or more + polygons that do not overlap. For example, you could use a multipolygon shape + to represent the body of land that consists of an island surrounded by an + atoll: the inner island would be one `MGLPolygon` object, while the surrounding + atoll would be another. You could also use a multipolygon shape to represent a + group of disconnected but related buildings. + + You can add multipolygon shapes to the map by adding them to an + `MGLShapeSource` object. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s multipolygons collectively using an `MGLFillStyleLayer` or + `MGLSymbolStyleLayer` object. - @note `MGLMultiPolygon` objects cannot be added to a map view using - `-[MGLMapView addAnnotations:]` and related methods. + You cannot add an `MGLMultiPolygon` object directly to a map view using + `-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can + add the `polygons` array’s items as overlays individually. */ @interface MGLMultiPolygon : MGLShape diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h index cb98df9a1b..429ba9cddc 100644 --- a/platform/darwin/src/MGLPolyline.h +++ b/platform/darwin/src/MGLPolyline.h @@ -9,10 +9,35 @@ NS_ASSUME_NONNULL_BEGIN /** - The `MGLPolyline` class represents a shape consisting of one or more points - that define connecting line segments. The points are connected end-to-end in - the order they are provided. The first and last points are not connected to - each other. + An `MGLPolyline` object represents a shape consisting of two or more vertices, + specified as `CLLocationCoordinate2D` instances, and the line segments that + connect them. For example, you could use an polyline to represent a road or the + path along which something moves. + + You can add polyline shapes to the map by adding them to an `MGLShapeSource` + object. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s polylines collectively using an `MGLLineStyleLayer` or + `MGLSymbolStyleLayer` object. + + Alternatively, you can add a polyline overlay directly to a map view using the + `-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]` method. Configure + a polyline overlay’s appearance using + `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` and + `-[MGLMapViewDelegate mapView:lineWidthForPolylineAnnotation:]`. + + The vertices are automatically connected in the order in which you provide + them. The first and last vertices are not connected to each other, but you can + specify the same `CLLocationCoordinate2D` as the first and last vertices in + order to close the polyline. To fill the space within the shape, use an + `MGLPolygon` object. To group multiple polylines together in one shape, use an + `MGLMultiPolyline` or `MGLShapeCollection` object. + + To make the polyline straddle the antimeridian, specify some longitudes less + than −180 degrees or greater than 180 degrees. + + A polyline is known as a + LineString + geometry in GeoJSON. */ @interface MGLPolyline : MGLMultiPoint @@ -30,14 +55,23 @@ NS_ASSUME_NONNULL_BEGIN @end /** - The `MGLMultiPolyline` class represents a shape consisting of one or more - polylines. For example, you could use an `MGLMultiPolyline` object to represent - both sides of a divided highway (dual carriageway), excluding the median - (central reservation): each carriageway would be a distinct `MGLPolyline` - object. - - @note `MGLMultiPolyline` objects cannot be added to a map view using - `-[MGLMapView addAnnotations:]` and related methods. + An `MGLMultiPolyline` object represents a shape consisting of one or more + polylines. For example, you could use a multipolyline shape to represent both + sides of a divided highway (dual carriageway), excluding the median (central + reservation): each carriageway would be a distinct `MGLPolyline` object. + + You can add multipolyline shapes to the map by adding them to an + `MGLShapeSource` object. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s multipolylines collectively using an `MGLLineStyleLayer` or + `MGLSymbolStyleLayer` object. + + You cannot add an `MGLMultiPolyline` object directly to a map view using + `-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can + add the `polylines` array’s items as overlays individually. + + A multipolyline is known as a + MultiLineString + geometry in GeoJSON. */ @interface MGLMultiPolyline : MGLShape diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h index def5221d62..52b2f8aff6 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.h +++ b/platform/darwin/src/MGLRasterStyleLayer.h @@ -7,80 +7,111 @@ NS_ASSUME_NONNULL_BEGIN /** - A raster layer which allows customization of styling properties at runtime. You may - instantiate a new raster layer to add to a map style or you may query an - `MGLMapView` for its `style` and obtain existing layers using the - `-[MGLStyle layerWithIdentifier:]` method. + An `MGLRasterStyleLayer` is a style layer that renders raster tiles on the map. + + Use a raster style layer to configure the color parameters of raster tiles + loaded by an `MGLRasterSource` object. For example, you could use a raster + style layer to render Mapbox + Satellite imagery, a raster tile + set uploaded to Mapbox Studio, or a raster map authored in TileMill, the classic + Mapbox Editor, or Mapbox Studio Classic. + + You can access an existing raster style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new raster style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. */ @interface MGLRasterStyleLayer : MGLForegroundStyleLayer #pragma mark - Accessing the Paint Attributes /** - Increase or reduce the brightness of the image. The value is the maximum brightness. + Increase or reduce the brightness of the image. The value is the maximum + brightness. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. - This attribute corresponds to the raster-brightness-max paint property in the Mapbox Style Specification. + This attribute corresponds to the raster-brightness-max + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *maximumRasterBrightness; - @property (nonatomic, null_resettable) MGLStyleValue *rasterBrightnessMax __attribute__((unavailable("Use maximumRasterBrightness instead."))); /** - Increase or reduce the brightness of the image. The value is the minimum brightness. + Increase or reduce the brightness of the image. The value is the minimum + brightness. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. - This attribute corresponds to the raster-brightness-min paint property in the Mapbox Style Specification. + This attribute corresponds to the raster-brightness-min + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *minimumRasterBrightness; - @property (nonatomic, null_resettable) MGLStyleValue *rasterBrightnessMin __attribute__((unavailable("Use minimumRasterBrightness instead."))); /** Increase or reduce the contrast of the image. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *rasterContrast; /** Fade duration when a new tile is added. - + This property is measured in milliseconds. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `300`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `300`. Set this property to `nil` to + reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *rasterFadeDuration; /** Rotates hues around the color wheel. - + This property is measured in degrees. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. - This attribute corresponds to the raster-hue-rotate paint property in the Mapbox Style Specification. + This attribute corresponds to the raster-hue-rotate + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *rasterHueRotation; - @property (nonatomic, null_resettable) MGLStyleValue *rasterHueRotate __attribute__((unavailable("Use rasterHueRotation instead."))); /** The opacity at which the image will be drawn. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *rasterOpacity; /** Increase or reduce the saturation of the image. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *rasterSaturation; diff --git a/platform/darwin/src/MGLShape.h b/platform/darwin/src/MGLShape.h index af815da0e9..ecb66118a1 100644 --- a/platform/darwin/src/MGLShape.h +++ b/platform/darwin/src/MGLShape.h @@ -5,11 +5,23 @@ NS_ASSUME_NONNULL_BEGIN /** - The `MGLShape` class is an abstract class that defines the basic properties for - all shape-based annotation objects. This class must be subclassed and cannot be - used as is. Subclasses are responsible for defining the geometry of the shape - and providing an appropriate value for the coordinate property inherited from - the `MGLAnnotation` protocol. + `MGLShape` is an abstract class that represents a shape or annotation. Shapes + constitute the content of a map – not only the overlays atop the map, but also + the content that forms the base map. + + You do not create instances of this class directly or create subclasses of this + class. Instead, you create instances of `MGLPointAnnotation`, + `MGLPointCollection`, `MGLPolyline`, `MGLMultiPolyline`, `MGLPolygon`, + `MGLMultiPolygon`, or `MGLShapeCollection`. The shape classes correspond to the + Geometry object + types in the GeoJSON standard, but some have nonstandard names for backwards + compatibility. + + You can add shapes to the map by adding them to an `MGLShapeSource` object. + Configure the appearance of an `MGLShapeSource`’s or `MGLVectorSource`’s shapes + collectively using a concrete instance of `MGLVectorStyleLayer`. Alternatively, + you can add some kinds of shapes directly to a map view as annotations or + overlays. */ @interface MGLShape : NSObject @@ -38,21 +50,34 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Accessing the Shape Attributes /** - The title of the shape annotation. The default value of this property is `nil`. + The title of the shape annotation. + + The default value of this property is `nil`. + + This property is ignored when the shape is used in an `MGLShapeSource`. To name + a shape used in a shape source, create an `MGLFeature` and add an attribute to + the `MGLFeature.attributes` property. */ @property (nonatomic, copy, nullable) NSString *title; /** The subtitle of the shape annotation. The default value of this property is `nil`. + + This property is ignored when the shape is used in an `MGLShapeSource`. To + provide additional information about a shape used in a shape source, create an + `MGLFeature` and add an attribute to the `MGLFeature.attributes` property. */ @property (nonatomic, copy, nullable) NSString *subtitle; #if !TARGET_OS_IPHONE /** - The tooltip of the shape annotation. The default value of this property is - `nil`. + The tooltip of the shape annotation. + + The default value of this property is `nil`. + + This property is ignored when the shape is used in an `MGLShapeSource`. */ @property (nonatomic, copy, nullable) NSString *toolTip; diff --git a/platform/darwin/src/MGLShapeCollection.h b/platform/darwin/src/MGLShapeCollection.h index a617223ea7..343c2a4322 100644 --- a/platform/darwin/src/MGLShapeCollection.h +++ b/platform/darwin/src/MGLShapeCollection.h @@ -7,12 +7,30 @@ NS_ASSUME_NONNULL_BEGIN /** - The `MGLShapeCollection` class represents a shape consisting of one or more + An `MGLShapeCollection` object represents a shape consisting of one or more distinct but related shapes that are instances of `MGLShape`. The constituent shapes can be a mixture of different kinds of shapes. - @note `MGLShapeCollection` objects cannot be added to a map view using - `-[MGLMapView addAnnotations:]` and related methods. + `MGLShapeCollection` is most commonly used to add multiple shapes to a single + `MGLShapeSource`. Configure the appearance of an `MGLShapeSource`’s or + `MGLVectorSource`’s shape collection collectively using an + `MGLSymbolStyleLayer` object, or use multiple instances of + `MGLCircleStyleLayer`, `MGLFillStyleLayer`, and `MGLLineStyleLayer` to + configure the appearance of each kind of shape inside the collection. + + You cannot add an `MGLShapeCollection` object directly to a map view as an + annotation. However, you can create individual `MGLPointAnnotation`, + `MGLPolyline`, and `MGLPolygon` objects from the `shapes` array and add those + annotation objects to the map view using the `-[MGLMapView addAnnotations:]` + method. + + To represent a collection of point, polyline, or polygon shapes, it may be more + convenient to use an `MGLPointCollection`, `MGLMultiPolyline`, or + `MGLMultiPolygon` object, respectively. + + A multipolyline is known as a + GeometryCollection + geometry in GeoJSON. */ @interface MGLShapeCollection : MGLShape diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index 96dd502c30..1e0b87a73f 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -40,7 +40,7 @@ static const NSInteger MGLStyleDefaultVersion = 9; via `-[MGLMapView style]` by updating the style's data sources or layers. @note Wait until the map style has finished loading before modifying a map's - style via any of the MGLStyle instance methods below. + style via any of the `MGLStyle` instance methods below. You can use the `MGLMapViewDelegate` methods `-mapViewDidFinishLoadingMap:` or `-mapView:didFinishLoadingStyle:` as indicators that it's safe to modify the map's style. diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs index 3b576e766b..2754cca1c5 100644 --- a/platform/darwin/src/MGLStyleLayer.h.ejs +++ b/platform/darwin/src/MGLStyleLayer.h.ejs @@ -1,9 +1,8 @@ <% + const doc = locals.doc; const type = locals.type; const layoutProperties = locals.layoutProperties; const paintProperties = locals.paintProperties; - const layoutPropertiesByName = locals.layoutPropertiesByName; - const paintPropertiesByName = locals.paintPropertiesByName; -%> // This file is generated. // Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`. @@ -20,14 +19,15 @@ NS_ASSUME_NONNULL_BEGIN <% for (const property of layoutProperties) { -%> <% if (property.type == "enum") { -%> /** - <%- propertyDoc(property.name, property, type) %> +<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %> - Values of this type are used in the `<%- camelizeWithLeadingLowercase(property.name) %>` property of `MGL<%- camelize(type) %>StyleLayer`. + Values of this type are used in the `MGL<%- camelize(type) %>StyleLayer.<%- camelizeWithLeadingLowercase(property.name) %>` + property. */ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% for (const value in property.values) { -%> /** - <%- propertyDoc(property.name, property.values[value], type) %> +<%- propertyDoc(property.name, property.values[value], type, 'enum').wrap(80, 4+1) %> */ MGL<%- camelize(property.name) %><%- camelize(value) %>, <% } -%> @@ -38,14 +38,15 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% for (const property of paintProperties) { -%> <% if (property.type == "enum") { -%> /** - <%- propertyDoc(property.name, property, type) %> +<%- propertyDoc(property.name, property, type, 'enum').wrap(80, 1) %> - Values of this type are used in the `<%- camelizeWithLeadingLowercase(property.name) %>` property of `MGL<%- camelize(type) %>StyleLayer`. + Values of this type are used in the `MGL<%- camelize(type) %>StyleLayer.<%- camelizeWithLeadingLowercase(property.name) %>` + property. */ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% for (const value in property.values) { -%> /** - <%- propertyDoc(property.name, property.values[value], type) %> +<%- propertyDoc(property.name, property.values[value], type, 'enum').wrap(80, 4+1) %> */ MGL<%- camelize(property.name) %><%- camelize(value) %>, <% } -%> @@ -55,17 +56,17 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% } -%> <% if (type == 'background') { -%> /** - A map style's background layer is the bottommost layer and is used to style a color - or pattern to show below all other map features. You can query an `MGLMapView` for its - `style` and obtain the background layer using the `-[MGLStyle layerWithIdentifier:]` - method and passing `background` for the identifier. +<%- doc.wrap(80, 1) %> */ <% } else { -%> /** - A <%- type %> layer which allows customization of styling properties at runtime. You may - instantiate a new <%- type %> layer to add to a map style or you may query an - `MGLMapView` for its `style` and obtain existing layers using the - `-[MGLStyle layerWithIdentifier:]` method. +<%- doc.wrap(80, 1) %> + + You can access an existing <%- type %> style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new <%- type %> style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. */ <% } -%> @interface MGL<%- camelize(type) %>StyleLayer : MGL<%- @@ -83,18 +84,7 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% for (const property of layoutProperties) { -%> /** - <%- propertyDoc(property.name, property, type) %> -<% if ('default' in property) { -%> - - The default value of this property is <%- propertyDefault(property, type) %>.<% if (!property.required) { %> Set this property to `nil` to reset it to the default value.<% } %> -<% } if (property.requires) { -%> - - <%- propertyReqs(property, layoutPropertiesByName, type) %> -<% } -%> -<% if (property.original) { -%> - - This attribute corresponds to the <%- property.original -%> layout property in the Mapbox Style Specification. -<% } -%> +<%- propertyDoc(property.name, property, type, 'layout').wrap(80, 1) %> */ @property (nonatomic<% if (!property.required) { %>, null_resettable<% } if (property.getter) { %>, getter=<%- objCGetter(property) -%><% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; @@ -109,22 +99,11 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { <% for (const property of paintProperties) { -%> /** - <%- propertyDoc(property.name, property, type) %> -<% if ('default' in property) { -%> - - The default value of this property is <%- propertyDefault(property, type) %>.<% if (!property.required) { %> Set this property to `nil` to reset it to the default value.<% } %> -<% } if (property.requires) { -%> - - <%- propertyReqs(property, paintPropertiesByName, type) %> -<% } -%> -<% if (property.original) { -%> - - This attribute corresponds to the <%- property.original -%> paint property in the Mapbox Style Specification. -<% } -%> +<%- propertyDoc(property.name, property, type, 'paint').wrap(80, 1) %> */ @property (nonatomic<% if (!property.required) { %>, null_resettable<% } if (property.getter) { %>, getter=<%- objCGetter(property) -%><% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(property.name) %>; -<% if (property.original) { %> +<% if (property.original) { -%> @property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) MGLStyleValue<<%- propertyType(property, true) %>> *<%- camelizeWithLeadingLowercase(originalPropertyName(property)) %> __attribute__((unavailable("Use <%- camelizeWithLeadingLowercase(property.name) %> instead."))); <% } -%> diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index 5a216e0354..a7b47ad2bb 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -7,21 +7,29 @@ NS_ASSUME_NONNULL_BEGIN /** - In combination with `symbolPlacement`, determines the rotation behavior of icons. + In combination with `symbolPlacement`, determines the rotation behavior of + icons. - Values of this type are used in the `iconRotationAlignment` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.iconRotationAlignment` + property. */ typedef NS_ENUM(NSUInteger, MGLIconRotationAlignment) { /** - When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, aligns icons east-west. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, aligns icon x-axes with the line. + When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, aligns icons + east-west. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, + aligns icon x-axes with the line. */ MGLIconRotationAlignmentMap, /** - Produces icons whose x-axes are aligned with the x-axis of the viewport, regardless of the value of `symbolPlacement`. + Produces icons whose x-axes are aligned with the x-axis of the viewport, + regardless of the value of `symbolPlacement`. */ MGLIconRotationAlignmentViewport, /** - When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, this is equivalent to `MGLIconRotationAlignmentViewport`. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, this is equivalent to `MGLIconRotationAlignmentMap`. + When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, this is + equivalent to `MGLIconRotationAlignmentViewport`. When `symbolPlacement` is + set to `MGLSymbolPlacementLine`, this is equivalent to + `MGLIconRotationAlignmentMap`. */ MGLIconRotationAlignmentAuto, }; @@ -29,7 +37,8 @@ typedef NS_ENUM(NSUInteger, MGLIconRotationAlignment) { /** Scales the icon to fit around the associated text. - Values of this type are used in the `iconTextFit` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.iconTextFit` + property. */ typedef NS_ENUM(NSUInteger, MGLIconTextFit) { /** @@ -53,7 +62,8 @@ typedef NS_ENUM(NSUInteger, MGLIconTextFit) { /** Label placement relative to its geometry. - Values of this type are used in the `symbolPlacement` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.symbolPlacement` + property. */ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) { /** @@ -61,7 +71,8 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) { */ MGLSymbolPlacementPoint, /** - The label is placed along the line of the geometry. Can only be used on `LineString` and `Polygon` geometries. + The label is placed along the line of the geometry. Can only be used on + `LineString` and `Polygon` geometries. */ MGLSymbolPlacementLine, }; @@ -69,7 +80,8 @@ typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) { /** Part of the text placed closest to the anchor. - Values of this type are used in the `textAnchor` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.textAnchor` + property. */ typedef NS_ENUM(NSUInteger, MGLTextAnchor) { /** @@ -113,7 +125,8 @@ typedef NS_ENUM(NSUInteger, MGLTextAnchor) { /** Text justification options. - Values of this type are used in the `textJustification` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.textJustification` + property. */ typedef NS_ENUM(NSUInteger, MGLTextJustification) { /** @@ -133,7 +146,8 @@ typedef NS_ENUM(NSUInteger, MGLTextJustification) { /** Orientation of text when map is pitched. - Values of this type are used in the `textPitchAlignment` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.textPitchAlignment` + property. */ typedef NS_ENUM(NSUInteger, MGLTextPitchAlignment) { /** @@ -151,21 +165,29 @@ typedef NS_ENUM(NSUInteger, MGLTextPitchAlignment) { }; /** - In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text. + In combination with `symbolPlacement`, determines the rotation behavior of the + individual glyphs forming the text. - Values of this type are used in the `textRotationAlignment` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.textRotationAlignment` + property. */ typedef NS_ENUM(NSUInteger, MGLTextRotationAlignment) { /** - When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, aligns text east-west. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, aligns text x-axes with the line. + When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, aligns text + east-west. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, + aligns text x-axes with the line. */ MGLTextRotationAlignmentMap, /** - Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of `symbolPlacement`. + Produces glyphs whose x-axes are aligned with the x-axis of the viewport, + regardless of the value of `symbolPlacement`. */ MGLTextRotationAlignmentViewport, /** - When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, this is equivalent to `MGLTextRotationAlignmentViewport`. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, this is equivalent to `MGLTextRotationAlignmentMap`. + When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, this is + equivalent to `MGLTextRotationAlignmentViewport`. When `symbolPlacement` is + set to `MGLSymbolPlacementLine`, this is equivalent to + `MGLTextRotationAlignmentMap`. */ MGLTextRotationAlignmentAuto, }; @@ -173,7 +195,8 @@ typedef NS_ENUM(NSUInteger, MGLTextRotationAlignment) { /** Specifies how to capitalize text. - Values of this type are used in the `textTransform` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.textTransform` + property. */ typedef NS_ENUM(NSUInteger, MGLTextTransform) { /** @@ -193,7 +216,8 @@ typedef NS_ENUM(NSUInteger, MGLTextTransform) { /** Controls the translation reference point. - Values of this type are used in the `iconTranslateAnchor` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.iconTranslateAnchor` + property. */ typedef NS_ENUM(NSUInteger, MGLIconTranslateAnchor) { /** @@ -209,7 +233,8 @@ typedef NS_ENUM(NSUInteger, MGLIconTranslateAnchor) { /** Controls the translation reference point. - Values of this type are used in the `textTranslateAnchor` property of `MGLSymbolStyleLayer`. + Values of this type are used in the `MGLSymbolStyleLayer.textTranslateAnchor` + property. */ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** @@ -223,23 +248,37 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { }; /** - A symbol layer which allows customization of styling properties at runtime. You may - instantiate a new symbol layer to add to a map style or you may query an - `MGLMapView` for its `style` and obtain existing layers using the - `-[MGLStyle layerWithIdentifier:]` method. + An `MGLSymbolStyleLayer` is a style layer that renders icon and text labels at + points or along lines on the map. + + Use a symbol style layer to configure the visual appearance of labels for + features in vector tiles loaded by an `MGLVectorSource` object or `MGLShape` or + `MGLFeature` instances in an `MGLShapeSource` object. + + You can access an existing symbol style layer using the + `-[MGLStyle layerWithIdentifier:]` method if you know its identifier; + otherwise, find it using the `MGLStyle.layers` property. You can also create a + new symbol style layer and add it to the style using a method such as + `-[MGLStyle addLayer:]`. */ @interface MGLSymbolStyleLayer : MGLVectorStyleLayer #pragma mark - Accessing the Layout Attributes /** - If true, the icon will be visible even if it collides with other previously drawn symbols. + If true, the icon will be visible even if it collides with other previously + drawn symbols. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the icon-allow-overlap layout property in the Mapbox Style Specification. + This attribute corresponds to the icon-allow-overlap + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *iconAllowsOverlap; @@ -249,11 +288,16 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** If true, other symbols can be visible even if they collide with the icon. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the icon-ignore-placement layout property in the Mapbox Style Specification. + This attribute corresponds to the icon-ignore-placement + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *iconIgnoresPlacement; @@ -263,7 +307,9 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** A string with {tokens} replaced, referencing the data property to pull from. - This attribute corresponds to the icon-image layout property in the Mapbox Style Specification. + This attribute corresponds to the icon-image + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *iconImageName; @@ -273,42 +319,58 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Offset distance of icon from its anchor. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 from the left and 0 from the top. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 from the left and 0 + from the top. Set this property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconOffset; /** - If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not. + If true, text will display without their corresponding icons when the icon + collides with other symbols and the text does not. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `iconImageName` is non-`nil`, and `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and + `textField` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable, getter=isIconOptional) MGLStyleValue *iconOptional; /** - Size of the additional area around the icon bounding box used for detecting symbol collisions. - + Size of the additional area around the icon bounding box used for detecting + symbol collisions. + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `2`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconPadding; /** Rotates the icon clockwise. - + This property is measured in degrees. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the icon-rotate layout property in the Mapbox Style Specification. + This attribute corresponds to the icon-rotate + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *iconRotation; @@ -316,22 +378,31 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { @property (nonatomic, null_resettable) MGLStyleValue *iconRotate __attribute__((unavailable("Use iconRotation instead."))); /** - In combination with `symbolPlacement`, determines the rotation behavior of icons. + In combination with `symbolPlacement`, determines the rotation behavior of + icons. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentAuto`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLIconRotationAlignmentAuto`. Set this property + to `nil` to reset it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconRotationAlignment; /** Scale factor for icon. 1 is original size, 3 triples the size. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the icon-size layout property in the Mapbox Style Specification. + This attribute corresponds to the icon-size + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *iconScale; @@ -341,31 +412,47 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Scales the icon to fit around the associated text. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTextFitNone`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLIconTextFitNone`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`, and `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and + `textField` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTextFit; /** Size of the additional area added to dimensions determined by `iconTextFit`. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `NSEdgeInsetsZero` or `UIEdgeInsetsZero`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `NSEdgeInsetsZero` or `UIEdgeInsetsZero`. Set this + property to `nil` to reset it to the default value. - This property is only applied to the style if `iconImageName` is non-`nil`, and `textField` is non-`nil`, and `iconTextFit` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTextFitBoth`, `MGLIconTextFitWidth`, or `MGLIconTextFitHeight`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and + `textField` is non-`nil`, and `iconTextFit` is set to an `MGLStyleValue` object + containing an `NSValue` object containing `MGLIconTextFitBoth`, + `MGLIconTextFitWidth`, or `MGLIconTextFitHeight`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTextFitPadding; /** If true, the icon may be flipped to prevent it from being rendered upside-down. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `iconImageName` is non-`nil`, and `iconRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + This property is only applied to the style if `iconImageName` is non-`nil`, and + `iconRotationAlignment` is set to an `MGLStyleValue` object containing an + `NSValue` object containing `MGLIconRotationAlignmentMap`, and + `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` + object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. - This attribute corresponds to the icon-keep-upright layout property in the Mapbox Style Specification. + This attribute corresponds to the icon-keep-upright + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *keepsIconUpright; @@ -373,13 +460,22 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { @property (nonatomic, null_resettable) MGLStyleValue *iconKeepUpright __attribute__((unavailable("Use keepsIconUpright instead."))); /** - If true, the text may be flipped vertically to prevent it from being rendered upside-down. - - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`, and `textRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. - - This attribute corresponds to the text-keep-upright layout property in the Mapbox Style Specification. + If true, the text may be flipped vertically to prevent it from being rendered + upside-down. + + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `YES`. Set this property to `nil` to reset it to + the default value. + + This property is only applied to the style if `textField` is non-`nil`, and + `textRotationAlignment` is set to an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextRotationAlignmentMap`, and + `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` + object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + + This attribute corresponds to the text-keep-upright + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *keepsTextUpright; @@ -388,14 +484,20 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Maximum angle change between adjacent characters. - + This property is measured in degrees. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `45`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `45`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`, and + `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` + object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. - This attribute corresponds to the text-max-angle layout property in the Mapbox Style Specification. + This attribute corresponds to the text-max-angle + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *maximumTextAngle; @@ -404,14 +506,19 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** The maximum line width for text wrapping. - + This property is measured in ems. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `10`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `10`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the text-max-width layout property in the Mapbox Style Specification. + This attribute corresponds to the text-max-width + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *maximumTextWidth; @@ -419,11 +526,18 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { @property (nonatomic, null_resettable) MGLStyleValue *textMaxWidth __attribute__((unavailable("Use maximumTextWidth instead."))); /** - If true, the symbols will not cross tile edges to avoid mutual collisions. Recommended in layers that don't have enough padding in the vector tile to prevent collisions, or if it is a point symbol layer placed after a line symbol layer. - - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. - - This attribute corresponds to the symbol-avoid-edges layout property in the Mapbox Style Specification. + If true, the symbols will not cross tile edges to avoid mutual collisions. + Recommended in layers that don't have enough padding in the vector tile to + prevent collisions, or if it is a point symbol layer placed after a line symbol + layer. + + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. + + This attribute corresponds to the symbol-avoid-edges + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *symbolAvoidsEdges; @@ -433,29 +547,41 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Label placement relative to its geometry. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementPoint`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLSymbolPlacementPoint`. Set this property to + `nil` to reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *symbolPlacement; /** Distance between two symbol anchors. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `250`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `250`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored. + This property is only applied to the style if `symbolPlacement` is set to an + `MGLStyleValue` object containing an `NSValue` object containing + `MGLSymbolPlacementLine`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *symbolSpacing; /** - If true, the text will be visible even if it collides with other previously drawn symbols. + If true, the text will be visible even if it collides with other previously + drawn symbols. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the text-allow-overlap layout property in the Mapbox Style Specification. + This attribute corresponds to the text-allow-overlap + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *textAllowsOverlap; @@ -465,36 +591,49 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Part of the text placed closest to the anchor. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextAnchorCenter`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextAnchorCenter`. Set this property to `nil` + to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textAnchor; /** - Value to use for a text label. Feature properties are specified using tokens like {field_name}. + Value to use for a text label. Feature properties are specified using tokens + like {field_name}. - The default value of this property is an `MGLStyleValue` object containing the empty string. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing the + empty string. Set this property to `nil` to reset it to the default value. */ @property (nonatomic, null_resettable) MGLStyleValue *textField; /** Font stack to use for displaying text. - The default value of this property is an `MGLStyleValue` object containing the array `Open Sans Regular`, `Arial Unicode MS Regular`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing the + array `Open Sans Regular`, `Arial Unicode MS Regular`. Set this property to + `nil` to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *> *textFont; /** If true, other symbols can be visible even if they collide with the text. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the text-ignore-placement layout property in the Mapbox Style Specification. + This attribute corresponds to the text-ignore-placement + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *textIgnoresPlacement; @@ -504,11 +643,16 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Text justification options. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextJustificationCenter`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextJustificationCenter`. Set this property to + `nil` to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the text-justify layout property in the Mapbox Style Specification. + This attribute corresponds to the text-justify + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *textJustification; @@ -517,76 +661,102 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** Text tracking amount. - + This property is measured in ems. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textLetterSpacing; /** Text leading value for multi-line text. - + This property is measured in ems. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1.2`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1.2`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textLineHeight; /** Offset distance of text from its anchor. - + This property is measured in ems. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 ems from the left and 0 ems from the top. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 ems from the left and + 0 ems from the top. Set this property to `nil` to reset it to the default + value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textOffset; /** - If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not. + If true, icons will display without their corresponding text when the text + collides with other symbols and the icon does not. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing `NO`. Set this property to `nil` to reset it to + the default value. - This property is only applied to the style if `textField` is non-`nil`, and `iconImageName` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`, and + `iconImageName` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable, getter=isTextOptional) MGLStyleValue *textOptional; /** - Size of the additional area around the text bounding box used for detecting symbol collisions. - + Size of the additional area around the text bounding box used for detecting + symbol collisions. + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `2`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textPadding; /** Orientation of text when map is pitched. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextPitchAlignmentAuto`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextPitchAlignmentAuto`. Set this property to + `nil` to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textPitchAlignment; /** Rotates the text clockwise. - + This property is measured in degrees. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. - This attribute corresponds to the text-rotate layout property in the Mapbox Style Specification. + This attribute corresponds to the text-rotate + layout property in the Mapbox Style Specification. */ @property (nonatomic, null_resettable) MGLStyleValue *textRotation; @@ -594,31 +764,41 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { @property (nonatomic, null_resettable) MGLStyleValue *textRotate __attribute__((unavailable("Use textRotation instead."))); /** - In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text. + In combination with `symbolPlacement`, determines the rotation behavior of the + individual glyphs forming the text. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentAuto`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextRotationAlignmentAuto`. Set this property + to `nil` to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textRotationAlignment; /** Font size. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `16`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `16`. Set this property to `nil` to + reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textSize; /** Specifies how to capitalize text. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextTransformNone`. Set this property to `nil` to reset it to the default value. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextTransformNone`. Set this property to `nil` + to reset it to the default value. - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textTransform; @@ -626,92 +806,124 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { #if TARGET_OS_IPHONE /** - The tint color to apply to the icon. The `iconImageName` property must be set to a template image. + The tint color to apply to the icon. The `iconImageName` property must be set + to a template image. - The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconColor; #else /** - The tint color to apply to the icon. The `iconImageName` property must be set to a template image. + The tint color to apply to the icon. The `iconImageName` property must be set + to a template image. - The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconColor; #endif /** Fade out the halo towards the outside. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloBlur; #if TARGET_OS_IPHONE /** - The color of the icon’s halo. The `iconImageName` property must be set to a template image. + The color of the icon’s halo. The `iconImageName` property must be set to a + template image. - The default value of this property is an `MGLStyleValue` object containing `UIColor.clearColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.clearColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloColor; #else /** - The color of the icon’s halo. The `iconImageName` property must be set to a template image. + The color of the icon’s halo. The `iconImageName` property must be set to a + template image. - The default value of this property is an `MGLStyleValue` object containing `NSColor.clearColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.clearColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloColor; #endif /** Distance of halo to the icon outline. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconHaloWidth; /** The opacity at which the icon will be drawn. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconOpacity; /** Distance that the icon's anchor is moved from its original placement. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points from the left + and 0 points from the top. Set this property to `nil` to reset it to the + default value. + + This property is only applied to the style if `iconImageName` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTranslate; /** Controls the translation reference point. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconTranslateAnchorMap`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `iconImageName` is non-`nil`, and `iconTranslate` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLIconTranslateAnchorMap`. Set this property to + `nil` to reset it to the default value. + + This property is only applied to the style if `iconImageName` is non-`nil`, and + `iconTranslate` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *iconTranslateAnchor; @@ -719,30 +931,39 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** The color with which the text will be drawn. - The default value of this property is an `MGLStyleValue` object containing `UIColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textColor; #else /** The color with which the text will be drawn. - The default value of this property is an `MGLStyleValue` object containing `NSColor.blackColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.blackColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textColor; #endif /** The halo's fadeout distance towards the outside. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textHaloBlur; @@ -750,59 +971,79 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { /** The color of the text's halo, which helps it stand out from backgrounds. - The default value of this property is an `MGLStyleValue` object containing `UIColor.clearColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `UIColor.clearColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textHaloColor; #else /** The color of the text's halo, which helps it stand out from backgrounds. - The default value of this property is an `MGLStyleValue` object containing `NSColor.clearColor`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing + `NSColor.clearColor`. Set this property to `nil` to reset it to the default + value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textHaloColor; #endif /** - Distance of halo to the font outline. Max text halo width is 1/4 of the font-size. - + Distance of halo to the font outline. Max text halo width is 1/4 of the + font-size. + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `0`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textHaloWidth; /** The opacity at which the text will be drawn. - The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSNumber` object containing the float `1`. Set this property to `nil` to reset + it to the default value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textOpacity; /** Distance that the text's anchor is moved from its original placement. - + This property is measured in points. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing a `CGVector` struct set to 0 points from the left + and 0 points from the top. Set this property to `nil` to reset it to the + default value. + + This property is only applied to the style if `textField` is non-`nil`. + Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textTranslate; /** Controls the translation reference point. - The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextTranslateAnchorMap`. Set this property to `nil` to reset it to the default value. - - This property is only applied to the style if `textField` is non-`nil`, and `textTranslate` is non-`nil`. Otherwise, it is ignored. + The default value of this property is an `MGLStyleValue` object containing an + `NSValue` object containing `MGLTextTranslateAnchorMap`. Set this property to + `nil` to reset it to the default value. + + This property is only applied to the style if `textField` is non-`nil`, and + `textTranslate` is non-`nil`. Otherwise, it is ignored. */ @property (nonatomic, null_resettable) MGLStyleValue *textTranslateAnchor; diff --git a/platform/darwin/src/MGLVectorStyleLayer.m b/platform/darwin/src/MGLVectorStyleLayer.m index d8146f4246..da6da0ea7f 100644 --- a/platform/darwin/src/MGLVectorStyleLayer.m +++ b/platform/darwin/src/MGLVectorStyleLayer.m @@ -4,12 +4,12 @@ - (void)setPredicate:(NSPredicate *)predicate { [NSException raise:@"MGLAbstractClassException" - format:@"MGLVectorLayer is an abstract class"]; + format:@"MGLVectorStyleLayer is an abstract class"]; } - (NSPredicate *)predicate { [NSException raise:@"MGLAbstractClassException" - format:@"MGLVectorLayer is an abstract class"]; + format:@"MGLVectorStyleLayer is an abstract class"]; return nil; } diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 18763b68ee..f7d2080cf4 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -14,18 +14,18 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * A new runtime styling API allows you to adjust the style and content of the base map dynamically. All the options available in [Mapbox Studio](https://www.mapbox.com/studio/) are now exposed via MGLStyle and subclasses of MGLStyleLayer and MGLSource. ([#5727](https://github.com/mapbox/mapbox-gl-native/pull/5727)) * MGLMapView’s `styleURL` property can now be set to an absolute file URL. ([#6026](https://github.com/mapbox/mapbox-gl-native/pull/6026)) -* MGLShapeSource objects, as well as GeoJSON sources specified by the stylesheet at design time, now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) +* When creating an MGLShapeSource, you can now specify options for clustering point features within the shape source. Similarly, GeoJSON sources specified by the stylesheet at design time can specify the `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * Added [quadkey](https://msdn.microsoft.com/en-us/library/bb259689.aspx) support and limited WMS support in raster tile URL templates. ([#5628](https://github.com/mapbox/mapbox-gl-native/pull/5628)) -* TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) +* When creating an MGLTileSource, you can now specify that the tile URLs use [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates by setting `MGLTileSourceOptionTileCoordinateSystem` to `MGLTileCoordinateSystemTMS`. TileJSON files can specify `"scheme": "tms"`. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) * Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * `-[MGLMapView resetPosition]` now resets to the current style’s default center coordinates, zoom level, direction, and pitch, if specified. ([#6127](https://github.com/mapbox/mapbox-gl-native/pull/6127)) * Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) * MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728)) * The action sheet that appears when tapping the information button in the bottom-right corner now lists the correct attribution for the current style. ([#5999](https://github.com/mapbox/mapbox-gl-native/pull/5999)) -* The `text-pitch-alignment` property is now supported in stylesheets for improved street label legibility on a tilted map. ([#5288](https://github.com/mapbox/mapbox-gl-native/pull/5288)) -* The `icon-text-fit` and `icon-text-fit-padding` properties are now supported in stylesheets, allowing the background of a shield to automatically resize to fit the shield’s text. ([#5334](https://github.com/mapbox/mapbox-gl-native/pull/5334)) -* The `circle-pitch-scale` property is now supported in stylesheets, allowing circle features in a tilted base map to scale or remain the same size as the viewing distance changes. ([#5576](https://github.com/mapbox/mapbox-gl-native/pull/5576)) +* Added support for MGLSymbolStyleLayer’s `textPitchAlignment` property and the corresponding style JSON property for improved street label legibility on a tilted map. ([#5288](https://github.com/mapbox/mapbox-gl-native/pull/5288)) +* Added support for MGLSymbolStyleLayer’s `iconTextFit` and `iconTextFitPadding` properties and the corresponding style JSON properties, allowing the background of a shield to automatically resize to fit the shield’s text. ([#5334](https://github.com/mapbox/mapbox-gl-native/pull/5334)) +* Added support for MGLSymbolStyleLayer’s `circlePitchScale` property and the corresponding style JSON property, allowing circle features in a tilted base map to scale or remain the same size as the viewing distance changes. ([#5576](https://github.com/mapbox/mapbox-gl-native/pull/5576)) * The `identifier` property of an MGLFeature may now be either a number or string. ([#5514](https://github.com/mapbox/mapbox-gl-native/pull/5514)) * If MGLMapView is unable to obtain or parse a style, it now calls its delegate’s `-mapViewDidFailLoadingMap:withError:` method. ([#6145](https://github.com/mapbox/mapbox-gl-native/pull/6145)) * Added the `-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]` delegate method, which offers the earliest opportunity to modify the layout or appearance of the current style before the map view is displayed to the user. ([#6636](https://github.com/mapbox/mapbox-gl-native/pull/6636)) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index 8482cc5e0b..d53874f5c9 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -2,6 +2,8 @@ ## 0.3.0 +This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox iOS SDK. The two SDKs have very similar feature sets. The main differences are the lack of user location tracking and annotation views. Some APIs have been adapted to macOS conventions, particularly the use of NSPopover for callout views. + ### Packaging * Fixed an issue causing code signing failures and bloating the framework. ([#5850](https://github.com/mapbox/mapbox-gl-native/pull/5850)) @@ -13,8 +15,8 @@ * A new runtime styling API allows you to adjust the style and content of the base map dynamically. All the options available in [Mapbox Studio](https://www.mapbox.com/studio/) are now exposed via MGLStyle and subclasses of MGLStyleLayer and MGLSource. ([#5727](https://github.com/mapbox/mapbox-gl-native/pull/5727)) * MGLMapView’s `styleURL` property can now be set to an absolute file URL. ([#6026](https://github.com/mapbox/mapbox-gl-native/pull/6026)) -* MGLShapeSource objects, as well as GeoJSON sources specified by the stylesheet at design time, now support `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes for clustering point features on the base map. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) -* TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) +* When creating an MGLShapeSource, you can now specify options for clustering point features within the shape source. Similarly, GeoJSON sources specified by the stylesheet at design time can specify the `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) +* When creating an MGLTileSource, you can now specify that the tile URLs use [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates by setting `MGLTileSourceOptionTileCoordinateSystem` to `MGLTileCoordinateSystemTMS`. TileJSON files can specify `"scheme": "tms"`. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) * Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811)) diff --git a/platform/macos/src/MGLMapViewDelegate.h b/platform/macos/src/MGLMapViewDelegate.h index c5af93f8ad..e07378bf16 100644 --- a/platform/macos/src/MGLMapViewDelegate.h +++ b/platform/macos/src/MGLMapViewDelegate.h @@ -257,7 +257,7 @@ NS_ASSUME_NONNULL_BEGIN such as `title` and `subtitle`. If each annotation should have an identical callout, you can set the - `MGLMapView` instance’s `-setCalloutViewController:` method instead. + `MGLMapView.calloutViewController` property instead. @param mapView The map view that is requesting a callout view controller. @param annotation The object representing the annotation. -- cgit v1.2.1 From 20b82c8fd1de49c096d5c6656401d18af262c46f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Tue, 20 Dec 2016 16:48:43 -0800 Subject: [ios, macos] Omit perspectiveSkew from drawing context struct --- platform/darwin/src/MGLOpenGLStyleLayer.h | 1 - platform/darwin/src/MGLOpenGLStyleLayer.mm | 1 - 2 files changed, 2 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h index 7cb6b147c2..f395484436 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.h +++ b/platform/darwin/src/MGLOpenGLStyleLayer.h @@ -14,7 +14,6 @@ typedef struct MGLStyleLayerDrawingContext { double zoomLevel; CLLocationDirection direction; CGFloat pitch; - CGFloat perspectiveSkew; } MGLStyleLayerDrawingContext; @interface MGLOpenGLStyleLayer : MGLStyleLayer diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm index ac2a6abcd9..12986f64c1 100644 --- a/platform/darwin/src/MGLOpenGLStyleLayer.mm +++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm @@ -34,7 +34,6 @@ void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRender .zoomLevel = params.zoom, .direction = mbgl::util::wrap(params.bearing, 0., 360.), .pitch = static_cast(params.pitch), - .perspectiveSkew = static_cast(params.altitude), }; [layer drawInMapView:layer.mapView withContext:drawingContext]; } -- cgit v1.2.1 From 906d700ccd1aedf262b8a29b88203c614c105805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Tue, 20 Dec 2016 17:32:06 -0800 Subject: [ios, macos] Indicate protocols, abstract classes in documentation navigation (#7478) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [ios, macos] Italicize protocols, abstract classes in doc nav Italicize protocols and abstract classes in the generated documentation’s navigation sidebar. * [ios, macos] Denote protocols, abstract classes with glosses Instead of oblique text, use a parenthetical gloss to denote a protocol or abstract class. --- .../darwin/docs/theme/assets/css/jazzy.css.scss | 25 ++++++++++++++++++++++ platform/darwin/docs/theme/templates/nav.mustache | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) (limited to 'platform') diff --git a/platform/darwin/docs/theme/assets/css/jazzy.css.scss b/platform/darwin/docs/theme/assets/css/jazzy.css.scss index 9c1f347142..6b4dffc879 100644 --- a/platform/darwin/docs/theme/assets/css/jazzy.css.scss +++ b/platform/darwin/docs/theme/assets/css/jazzy.css.scss @@ -51,6 +51,7 @@ $navigation_bg_color: #fbfbfb; $navigation_task_color: $link_color; $section_name_color: $color_darkblue; +$navigation_gloss_color: #999; // ----- Content @@ -367,6 +368,30 @@ pre code { color: $navigation_task_color; } +%nav-group-task-gloss { + color: $navigation_gloss_color; + font-size: 90%; + margin-left: 0.5em; +} + +.nav-group-task[data-url^="Protocols/"] > .nav-group-task-link::after { + @extend %nav-group-task-gloss; + content: "(Protocol)"; +} + +.nav-group-task[data-name="MGLForegroundStyleLayer"], +.nav-group-task[data-name="MGLMultiPoint"], +.nav-group-task[data-name="MGLShape"], +.nav-group-task[data-name="MGLSource"], +.nav-group-task[data-name="MGLStyleLayer"], +.nav-group-task[data-name="MGLTileSource"], +.nav-group-task[data-name="MGLVectorStyleLayer"] { + .nav-group-task-link::after { + @extend %nav-group-task-gloss; + content: "(Abstract Class)"; + } +} + .nav-group-name > .small-heading, .nav-group-task-link { display: block; diff --git a/platform/darwin/docs/theme/templates/nav.mustache b/platform/darwin/docs/theme/templates/nav.mustache index 7584f49652..bfbd8e7d78 100644 --- a/platform/darwin/docs/theme/templates/nav.mustache +++ b/platform/darwin/docs/theme/templates/nav.mustache @@ -5,7 +5,7 @@ {{section}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Placeholder stringDescription
{x}The index of the tile along the map’s x axis according to Spherical + Mercator projection. If the value is 0, the tile’s left edge corresponds + to the 180th meridian west. If the value is 2z−1, + the tile’s right edge corresponds to the 180th meridian east.
{y}The index of the tile along the map’s y axis according to Spherical + Mercator projection. If the value is 0, the tile’s tile edge corresponds + to arctan(sinh(π)), or approximately 85.0511 degrees north. If the value + is 2z−1, the tile’s bottom edge corresponds to + −arctan(sinh(π)), or approximately 85.0511 degrees south. The y axis is + inverted if the options parameter contains + MGLTileSourceOptionTileCoordinateSystem with a value of + MGLTileCoordinateSystemTMS.
{z}The tile’s zoom level. At zoom level 0, each tile covers the entire + world map; at zoom level 1, it covers ¼ of the world; at zoom level 2, + 116 of the world, and so on. For tiles loaded by + a MGLRasterSource object, whether the tile zoom level + matches the map’s current zoom level depends on the value of the + source’s tile size as specified in the + MGLTileSourceOptionTileSize key of the + options parameter.
{bbox-epsg-3857}The tile’s bounding box, expressed as a comma-separated list of the + tile’s western, southern, eastern, and northern extents according to + Spherical Mercator (EPSG:3857) projection. The bounding box is typically + used with map services conforming to the + Web Map Service + protocol.
{quadkey}A quadkey indicating both the tile’s location and its zoom level. The + quadkey is typically used with + Bing Maps. +
{ratio}A suffix indicating the resolution of the tile image. The suffix is the + empty string for standard resolution displays and @2x for + Retina displays, including displays for which + NSScreen.backingScaleFactor or UIScreen.scale + is 3.
{prefix}Two hexadecimal digits chosen such that each visible tile has a + different prefix. The prefix is typically used for domain sharding.
+ + For more information about the `{x}`, `{y}`, and `{z}` placeholder strings, + consult the + OpenStreetMap Wiki. + @param identifier A string that uniquely identifies the source in the style to which it is added. - @param tileURLTemplates An array of tile URL template strings. + @param tileURLTemplates An array of tile URL template strings. Only the first + string is used; any additional strings are ignored. @param options A dictionary containing configuration options. See `MGLTileSourceOption` for available keys and values. Pass in `nil` to use the default values. -- cgit v1.2.1 From 077cbb5e4b889a457e5bad5557ed4f7fb3d9ac72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 23 Dec 2016 03:09:09 -0800 Subject: [ios, macos] Updated changelogs --- platform/ios/CHANGELOG.md | 2 ++ platform/macos/CHANGELOG.md | 2 ++ 2 files changed, 4 insertions(+) (limited to 'platform') diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index f7d2080cf4..47a1b8433d 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -8,6 +8,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Xcode 7.3 or above is required for using this SDK. ([#6059](https://github.com/mapbox/mapbox-gl-native/issues/6059)) * Clarified that the `-ObjC` linker flag is required for linking against the static framework distribution of this SDK. ([#6213](https://github.com/mapbox/mapbox-gl-native/pull/6213)) +* The API reference has a sharper look. ([#7422](https://github.com/mapbox/mapbox-gl-native/pull/7422)) * Added documentation for the Info.plist keys used by this SDK. ([#6833](https://github.com/mapbox/mapbox-gl-native/pull/6833)) ### Styles and data @@ -49,6 +50,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Added new methods to MGLMultiPoint for changing the vertices along a polyline annotation or the exterior of a polygon annotation. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) * Added new APIs to MGLMapView to query for visible annotations. Combined with `-[MGLMapView viewForAnnotation:]`, these APIs can be used to access all visible annotation views. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061)) +* Shape, feature, and annotation classes now conform to NSSecureCoding. ([#6559](https://github.com/mapbox/mapbox-gl-native/pull/6559)) * Fixed an issue causing offscreen annotation views to be updated even when they were in the reuse queue. ([#5987](https://github.com/mapbox/mapbox-gl-native/pull/5987)) * Fixed an issue preventing MGLAnnotationView from animating when its coordinate changes. ([#6215](https://github.com/mapbox/mapbox-gl-native/pull/6215)) * Fixed an issue causing the wrong annotation view to be selected when tapping an annotation view with a center offset applied. ([#5931](https://github.com/mapbox/mapbox-gl-native/pull/5931)) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index d53874f5c9..b00647747a 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -9,6 +9,7 @@ This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox * Fixed an issue causing code signing failures and bloating the framework. ([#5850](https://github.com/mapbox/mapbox-gl-native/pull/5850)) * Xcode 7.3 or higher is now required for using this SDK. ([#6059](https://github.com/mapbox/mapbox-gl-native/issues/6059)) * Fixed an issue with symbols not being properly stripped from the dynamic framework when built with `make xpackage SYMBOLS=NO`. ([#6531](https://github.com/mapbox/mapbox-gl-native/pull/6531)) +* The API reference has a sharper look. ([#7422](https://github.com/mapbox/mapbox-gl-native/pull/7422)) * Added documentation for the Info.plist keys used by this SDK. ([#6833](https://github.com/mapbox/mapbox-gl-native/pull/6833)) ### Styles and data @@ -38,6 +39,7 @@ This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox * Added new methods to MGLMultiPoint for changing the vertices along a polyline annotation or the exterior of a polygon annotation. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565)) * Added new APIs to MGLMapView to query for visible annotations. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061)) * Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706)) +* Shape, feature, and annotation classes now conform to NSSecureCoding. ([#6559](https://github.com/mapbox/mapbox-gl-native/pull/6559)) * Various method arguments that are represented as C arrays of `CLLocationCoordinate2D` instances have been marked `const` to streamline bridging to Swift. ([#7215](https://github.com/mapbox/mapbox-gl-native/pull/7215)) * To make an MGLPolyline or MGLPolygon span the antimeridian, specify coordinates with longitudes greater than 180° or less than −180°. ([#6088](https://github.com/mapbox/mapbox-gl-native/pull/6088)) * Fixed an issue where placing a point annotation on Null Island also placed a duplicate annotation on its antipode. ([#3563](https://github.com/mapbox/mapbox-gl-native/pull/3563)) -- cgit v1.2.1 From 2c62f0a15bed02bc6ca014fd113d5e62d9808624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 17 Dec 2016 15:39:43 -0800 Subject: [ios, macos] Fixed null expression crash Convert NSNull into an mbgl null value. --- platform/darwin/src/NSExpression+MGLAdditions.mm | 5 +++-- platform/darwin/test/MGLExpressionTests.mm | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 392a6d7f5b..6af069487e 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -55,9 +55,10 @@ // We use long long here to avoid any truncation. return { (int64_t)number.longLongValue }; } + } else if (value != [NSNull null]) { + [NSException raise:@"Value not handled" + format:@"Can’t convert %s:%@ to mbgl::Value", [value objCType], value]; } - [NSException raise:@"Value not handled" - format:@"Can’t convert %s:%@ to mbgl::Value", [value objCType], value]; return { }; } diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index 971f7d0e54..e78f87a99b 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -197,4 +197,13 @@ } } +#pragma mark - Null Tests + +- (void)testExpressionConversionNull +{ + NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNull null]]; + mbgl::Value convertedValue = predicate.rightExpression.mgl_filterValue; + XCTAssertTrue(convertedValue.is()); +} + @end -- cgit v1.2.1 From b134215895af5c2b94bb966e5b3f234679661c21 Mon Sep 17 00:00:00 2001 From: Jesse Bounds Date: Fri, 23 Dec 2016 08:33:27 -0800 Subject: [ios] Release beta 6 (#7535) --- platform/ios/Mapbox-iOS-SDK-symbols.podspec | 2 +- platform/ios/Mapbox-iOS-SDK.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec index 2cf3695af1..0ffc00a525 100644 --- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec +++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.4.0-beta.5-symbols' + m.version = '3.4.0-beta.6-symbols' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec index 8bc963f910..79e770ad32 100644 --- a/platform/ios/Mapbox-iOS-SDK.podspec +++ b/platform/ios/Mapbox-iOS-SDK.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |m| m.name = 'Mapbox-iOS-SDK' - m.version = '3.4.0-beta.5' + m.version = '3.4.0-beta.6' m.summary = 'Open source vector map solution for iOS with full styling capabilities.' m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.' -- cgit v1.2.1 From a66b1f7599bba67dce669b000a7d37d61010377f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 19 Dec 2016 00:24:20 -0800 Subject: [ios, macos] Fixed iosbench build Fixed a stale include in iosbench. MGLMapView(Private) forward-declares mbgl::Map instead of including mbgl.hpp, which iosbench has no access to. --- platform/darwin/src/MGLRasterSource.mm | 1 + platform/darwin/src/MGLShapeSource.mm | 1 + platform/darwin/src/MGLStyleLayer_Private.h | 1 + platform/darwin/src/MGLVectorSource.mm | 1 + platform/ios/benchmark/MBXBenchViewController.mm | 2 +- platform/ios/src/MGLMapView_Private.h | 6 ++++-- platform/macos/src/MGLMapView_Private.h | 4 +++- 7 files changed, 12 insertions(+), 4 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm index 9f57bb10a3..dbcba85d91 100644 --- a/platform/darwin/src/MGLRasterSource.mm +++ b/platform/darwin/src/MGLRasterSource.mm @@ -5,6 +5,7 @@ #import "MGLTileSource_Private.h" #import "NSURL+MGLAdditions.h" +#include #include const MGLTileSourceOption MGLTileSourceOptionTileSize = @"MGLTileSourceOptionTileSize"; diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm index d062e656c2..0647236e80 100644 --- a/platform/darwin/src/MGLShapeSource.mm +++ b/platform/darwin/src/MGLShapeSource.mm @@ -7,6 +7,7 @@ #import "NSURL+MGLAdditions.h" +#include #include const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered"; diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h index 8f1cdfb4a1..c5e3e76549 100644 --- a/platform/darwin/src/MGLStyleLayer_Private.h +++ b/platform/darwin/src/MGLStyleLayer_Private.h @@ -3,6 +3,7 @@ #import "MGLStyleLayer.h" #import "MGLStyleValue_Private.h" +#include #include NS_ASSUME_NONNULL_BEGIN diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index 3ec54ac094..c95ff63bbf 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -5,6 +5,7 @@ #import "MGLTileSource_Private.h" #import "NSURL+MGLAdditions.h" +#include #include @interface MGLVectorSource () diff --git a/platform/ios/benchmark/MBXBenchViewController.mm b/platform/ios/benchmark/MBXBenchViewController.mm index 43e98d7ccd..4f26d0cb1d 100644 --- a/platform/ios/benchmark/MBXBenchViewController.mm +++ b/platform/ios/benchmark/MBXBenchViewController.mm @@ -3,7 +3,7 @@ #import "MBXBenchAppDelegate.h" #import -#import "MGLMapView_Internal.h" +#import "MGLMapView_Private.h" #include "locations.hpp" diff --git a/platform/ios/src/MGLMapView_Private.h b/platform/ios/src/MGLMapView_Private.h index 5c74ba6dc8..4e2765377c 100644 --- a/platform/ios/src/MGLMapView_Private.h +++ b/platform/ios/src/MGLMapView_Private.h @@ -1,11 +1,13 @@ #import -#include +namespace mbgl { + class Map; +} /// Minimum size of an annotation’s accessibility element. extern const CGSize MGLAnnotationAccessibilityElementMinimumSize; -@interface MGLMapView (Internal) +@interface MGLMapView (Private) /// Currently shown popover representing the selected annotation. @property (nonatomic) UIView *calloutViewForSelectedAnnotation; diff --git a/platform/macos/src/MGLMapView_Private.h b/platform/macos/src/MGLMapView_Private.h index f0a61773a9..5ac75768a1 100644 --- a/platform/macos/src/MGLMapView_Private.h +++ b/platform/macos/src/MGLMapView_Private.h @@ -1,6 +1,8 @@ #import "MGLMapView.h" -#import +namespace mbgl { + class Map; +} @interface MGLMapView (Private) -- cgit v1.2.1 From f03cfd8bd50765556e76dcf11e9ae19c94a066cf Mon Sep 17 00:00:00 2001 From: Jason Wray Date: Fri, 23 Dec 2016 19:40:54 -0500 Subject: [ios] Document that offline pack resource removal is not guaranteed (#7522) Text adapted from: https://www.mapbox.com/help/mobile-offline/#removing-offline-regions --- platform/darwin/src/MGLOfflineStorage.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h index c58907d0d5..6e60f26e77 100644 --- a/platform/darwin/src/MGLOfflineStorage.h +++ b/platform/darwin/src/MGLOfflineStorage.h @@ -182,8 +182,8 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error - (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(nullable MGLOfflinePackAdditionCompletionHandler)completion; /** - Unregisters the given offline pack and frees any resources that are no longer - required by any remaining packs. + Unregisters the given offline pack and allows resources that are no longer + required by any remaining packs to be potentially freed. As soon as this method is called on a pack, the pack becomes invalid; any attempt to send it a message will result in an exception being thrown. If an @@ -195,6 +195,13 @@ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error KVO change notifications on the shared offline storage object’s `packs` key path. Removals from that array result in an `NSKeyValueChangeRemoval` change. + When you remove an offline pack, any resources that are required by that pack, + but not other packs, become eligible for deletion from offline storage. Because + the backing store used for offline storage is also used as a general purpose + cache for map resources, such resources may not be immediately removed if the + implementation determines that they remain useful for general performance of + the map. + @param pack The offline pack to remove. @param completion The completion handler to call once the pack has been removed. This handler is executed asynchronously on the main queue. -- cgit v1.2.1 From d35f235dae5e9dd2c825e217c72992f81f7f6661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 23 Dec 2016 15:49:41 -0800 Subject: [ios, macos] Aliased MGLMultiPointFeature to MGLPointCollectionFeature --- platform/darwin/src/MGLFeature.h | 3 +++ platform/ios/CHANGELOG.md | 2 +- platform/macos/CHANGELOG.md | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h index e05c37720d..30abcb1934 100644 --- a/platform/darwin/src/MGLFeature.h +++ b/platform/darwin/src/MGLFeature.h @@ -180,6 +180,9 @@ NS_ASSUME_NONNULL_BEGIN @interface MGLPointCollectionFeature : MGLPointCollection @end +// https://github.com/mapbox/mapbox-gl-native/issues/7473 +@compatibility_alias MGLMultiPointFeature MGLPointCollectionFeature; + /** An `MGLMultiPolylineFeature` object associates a multipolyline shape with an optional identifier and attributes. diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 47a1b8433d..ca86e5b34c 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -18,7 +18,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * When creating an MGLShapeSource, you can now specify options for clustering point features within the shape source. Similarly, GeoJSON sources specified by the stylesheet at design time can specify the `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * Added [quadkey](https://msdn.microsoft.com/en-us/library/bb259689.aspx) support and limited WMS support in raster tile URL templates. ([#5628](https://github.com/mapbox/mapbox-gl-native/pull/5628)) * When creating an MGLTileSource, you can now specify that the tile URLs use [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates by setting `MGLTileSourceOptionTileCoordinateSystem` to `MGLTileCoordinateSystemTMS`. TileJSON files can specify `"scheme": "tms"`. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) -* Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) +* Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. MGLMultiPointFeature is now an alias of MGLPointCollectionFeature. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * `-[MGLMapView resetPosition]` now resets to the current style’s default center coordinates, zoom level, direction, and pitch, if specified. ([#6127](https://github.com/mapbox/mapbox-gl-native/pull/6127)) * Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index b00647747a..e16908232f 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -18,7 +18,7 @@ This version of the Mapbox macOS SDK corresponds to version 3.4.0 of the Mapbox * MGLMapView’s `styleURL` property can now be set to an absolute file URL. ([#6026](https://github.com/mapbox/mapbox-gl-native/pull/6026)) * When creating an MGLShapeSource, you can now specify options for clustering point features within the shape source. Similarly, GeoJSON sources specified by the stylesheet at design time can specify the `cluster`, `clusterMaxZoom`, and `clusterRadius` attributes. ([#5724](https://github.com/mapbox/mapbox-gl-native/pull/5724)) * When creating an MGLTileSource, you can now specify that the tile URLs use [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates by setting `MGLTileSourceOptionTileCoordinateSystem` to `MGLTileCoordinateSystemTMS`. TileJSON files can specify `"scheme": "tms"`. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270)) -* Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) +* Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. MGLMultiPointFeature is now an alias of MGLPointCollectionFeature. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742)) * Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908)) * Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811)) * Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773)) -- cgit v1.2.1 From 1aab26e3157db787eefe9df7318d3eee009ca802 Mon Sep 17 00:00:00 2001 From: Fredrik Karlsson Date: Tue, 3 Jan 2017 10:25:17 +0100 Subject: Implement MGLForegroundStyleLayer.sourceIdentifier (#7570) * [ios, macos] sourceIdentifier accessor methods * [ios, macos] generate style code --- platform/darwin/src/MGLCircleStyleLayer.mm | 7 +++++++ platform/darwin/src/MGLFillStyleLayer.mm | 7 +++++++ platform/darwin/src/MGLLineStyleLayer.mm | 7 +++++++ platform/darwin/src/MGLRasterStyleLayer.mm | 7 +++++++ platform/darwin/src/MGLStyleLayer.mm.ejs | 12 ++++++++++-- platform/darwin/src/MGLSymbolStyleLayer.mm | 7 +++++++ 6 files changed, 45 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm index 266f2d836e..25dd859606 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.mm +++ b/platform/darwin/src/MGLCircleStyleLayer.mm @@ -54,6 +54,13 @@ namespace mbgl { super.rawLayer = rawLayer; } +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm index 891ab85d0b..204a4e92cb 100644 --- a/platform/darwin/src/MGLFillStyleLayer.mm +++ b/platform/darwin/src/MGLFillStyleLayer.mm @@ -49,6 +49,13 @@ namespace mbgl { super.rawLayer = rawLayer; } +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index 48164ed0c8..ab58a35f7f 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -61,6 +61,13 @@ namespace mbgl { super.rawLayer = rawLayer; } +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm index e61532773c..ebe9e5f8f0 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.mm +++ b/platform/darwin/src/MGLRasterStyleLayer.mm @@ -41,6 +41,13 @@ super.rawLayer = rawLayer; } +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + #pragma mark - Adding to and removing from a map view - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index 6178eaad51..30bec0c79e 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -89,7 +89,15 @@ namespace mbgl { super.rawLayer = rawLayer; } -<% if (type !== 'background' && type !== 'raster') { -%> +<% if (type !== 'background') { -%> +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + +<% if (type !== 'raster') { -%> - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); @@ -119,7 +127,7 @@ namespace mbgl { return [NSPredicate mgl_predicateWithFilter:self.rawLayer->getFilter()]; } -<% } -%> +<% }} -%> #pragma mark - Adding to and removing from a map view - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index 31c584b473..464a3d9505 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -108,6 +108,13 @@ namespace mbgl { super.rawLayer = rawLayer; } +- (NSString *)sourceIdentifier +{ + MGLAssertStyleLayerIsValid(); + + return @(self.rawLayer->getSourceID().c_str()); +} + - (NSString *)sourceLayerIdentifier { MGLAssertStyleLayerIsValid(); -- cgit v1.2.1 From 01717af59f5700cc22df17485bf2ba56eab65968 Mon Sep 17 00:00:00 2001 From: Eric Wolfe Date: Tue, 3 Jan 2017 14:40:14 -0800 Subject: [ios] Adds guides to documentation sidebar (#7488) Initial set of guides focused on runtime styling --- platform/ios/README.md | 2 +- platform/ios/docs/Info.plist Keys.md | 21 ----- platform/ios/docs/doc-README.md | 2 +- platform/ios/docs/guides/Adding Points to a Map.md | 84 ++++++++++++++++++ platform/ios/docs/guides/Info.plist Keys.md | 21 +++++ platform/ios/docs/guides/Runtime Styling.md | 57 ++++++++++++ .../ios/docs/guides/Working with Mapbox Studio.md | 97 +++++++++++++++++++++ .../docs/img/runtime-styling/CustomAnnotations.gif | Bin 0 -> 45604 bytes .../ios/docs/img/runtime-styling/DynamicStyles.gif | Bin 0 -> 97235 bytes platform/ios/docs/img/runtime-styling/Emoji.gif | Bin 0 -> 177077 bytes platform/ios/docs/img/runtime-styling/HexBins.gif | Bin 0 -> 554029 bytes .../ios/docs/img/runtime-styling/Population.gif | Bin 0 -> 247152 bytes .../ios/docs/img/runtime-styling/SnowLevels.gif | Bin 0 -> 489450 bytes platform/ios/docs/img/screenshot.png | Bin 0 -> 327733 bytes .../docs/img/studio-workflow/add-properties.gif | Bin 0 -> 239499 bytes .../docs/img/studio-workflow/create-polygons.gif | Bin 0 -> 1659146 bytes .../docs/img/studio-workflow/property-values.png | Bin 0 -> 83518 bytes .../docs/img/studio-workflow/stop-functions.png | Bin 0 -> 166947 bytes platform/ios/docs/pod-README.md | 2 +- platform/ios/jazzy.yml | 3 + platform/ios/screenshot.png | Bin 327733 -> 0 bytes platform/ios/scripts/document.sh | 4 +- 22 files changed, 267 insertions(+), 26 deletions(-) delete mode 100644 platform/ios/docs/Info.plist Keys.md create mode 100644 platform/ios/docs/guides/Adding Points to a Map.md create mode 100644 platform/ios/docs/guides/Info.plist Keys.md create mode 100644 platform/ios/docs/guides/Runtime Styling.md create mode 100644 platform/ios/docs/guides/Working with Mapbox Studio.md create mode 100644 platform/ios/docs/img/runtime-styling/CustomAnnotations.gif create mode 100644 platform/ios/docs/img/runtime-styling/DynamicStyles.gif create mode 100644 platform/ios/docs/img/runtime-styling/Emoji.gif create mode 100644 platform/ios/docs/img/runtime-styling/HexBins.gif create mode 100644 platform/ios/docs/img/runtime-styling/Population.gif create mode 100644 platform/ios/docs/img/runtime-styling/SnowLevels.gif create mode 100644 platform/ios/docs/img/screenshot.png create mode 100644 platform/ios/docs/img/studio-workflow/add-properties.gif create mode 100644 platform/ios/docs/img/studio-workflow/create-polygons.gif create mode 100644 platform/ios/docs/img/studio-workflow/property-values.png create mode 100644 platform/ios/docs/img/studio-workflow/stop-functions.png delete mode 100644 platform/ios/screenshot.png (limited to 'platform') diff --git a/platform/ios/README.md b/platform/ios/README.md index 2350d1e527..3d4cc3ff2b 100644 --- a/platform/ios/README.md +++ b/platform/ios/README.md @@ -9,4 +9,4 @@ This repository is for day-to-day development of the SDK. Building the SDK yours * [Integrating the Mapbox iOS SDK into your application](INSTALL.md) * [Contributing to the Mapbox iOS SDK](DEVELOPING.md) -![](screenshot.png) +![](docs/img/screenshot.png) diff --git a/platform/ios/docs/Info.plist Keys.md b/platform/ios/docs/Info.plist Keys.md deleted file mode 100644 index 34d3da9e29..0000000000 --- a/platform/ios/docs/Info.plist Keys.md +++ /dev/null @@ -1,21 +0,0 @@ -# Info.plist Keys - -The Mapbox iOS SDK supports custom `Info.plist` keys in your application in order to configure various settings. - -## MGLMapboxAccessToken - -Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/) to be used by all instances of `MGLMapView` in the current application. - -Mapbox-hosted vector tiles and styles require an API access token, which you can obtain from the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). Access tokens associate requests to Mapbox’s vector tile and style APIs with your Mapbox account. They also deter other developers from using your styles without your permission. - -As an alternative, you can use `+[MGLAccountManager setAccessToken:]` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private. - -## MGLMapboxAPIBaseURL - -Use this key if you need to customize the API base URL used throughout the SDK. If unset, the default Mapbox API is used. - -The default value is `https://api.mapbox.com`. - -## MGLMapboxMetricsEnabledSettingShownInApp - -If you have implemented custom opt-out of Mapbox Telemetry within the user interface of your app, use this key to disable the built-in check for opt-out support. See [this guide](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) for more details. diff --git a/platform/ios/docs/doc-README.md b/platform/ios/docs/doc-README.md index 22493b1502..e91bc0b1cc 100644 --- a/platform/ios/docs/doc-README.md +++ b/platform/ios/docs/doc-README.md @@ -2,7 +2,7 @@ The Mapbox iOS SDK is an open-source framework for embedding interactive map views with scalable, customizable vector maps into Cocoa Touch applications on iOS 7.0 and above using Objective-C, Swift, or Interface Builder. It takes stylesheets that conform to the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/), applies them to vector tiles that conform to the [Mapbox Vector Tile Specification](https://www.mapbox.com/developers/vector-tiles/), and renders them using OpenGL. -![Mapbox iOS SDK screenshots](screenshot.png) +![Mapbox iOS SDK screenshots](img/screenshot.png) For setup information, check out the [Mapbox iOS SDK homepage](https://www.mapbox.com/ios-sdk/). For detailed usage instructions, read “[First steps with the Mapbox iOS SDK](https://www.mapbox.com/help/first-steps-ios-sdk/)” and consult the [online examples](https://www.mapbox.com/ios-sdk/examples/). A [full changelog](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/ios/CHANGELOG.md) is also available. diff --git a/platform/ios/docs/guides/Adding Points to a Map.md b/platform/ios/docs/guides/Adding Points to a Map.md new file mode 100644 index 0000000000..5f89f4d6a8 --- /dev/null +++ b/platform/ios/docs/guides/Adding Points to a Map.md @@ -0,0 +1,84 @@ +# Adding Points to a Map + +Mapbox offers a few different ways to add points to a map, each with different tradeoffs. + +## MGLPointAnnotation + +It's straightforward to add an annotation to a map. You can use `MGLPointAnnotation` as is, or you can subclass it to add annotations with richer data. + +```swift +let annotation = MGLPointAnnotation() +annotation.coordinate = CLLocationCoordinate2D(latitude: 45.5076, longitude: -122.6736) +annotation.title = "Bobby's Coffee" +annotation.subtitle = "Coffeeshop" +mapView.addAnnotation(annotation) +``` + +See the `MGLMapViewDelegate` method `-mapView:annotationCanShowCallout:` and similar methods for allowing interaction with a callout. + +## Displaying annotations + +There are two basic ways to display the annotations you've added to a map, each with their own tradeoffs. + +### Annotation Images (`MGLAnnotationImage`) + +Annotation images are the quickest and most performant ways to display annotations, and you can provide your own custom annotation images ([example](https://www.mapbox.com/ios-sdk/examples/marker-image/)). + +By default, annotations added to the map are displayed with a red pin. If you'd like to customize this annotation, you can implement `MGLMapViewDelegate` `-mapView:imageForAnnotation:`. + +**Pros** + +* The easiest way to display a marker on a map +* Easily customizable with any `UIImage` +* High performance as the images are rendered directly in OpenGL + +**Cons** + +* Annotation images are purely static +* No control over z-ordering +* Limits to the size and number of images you can add + +### Annotation Views (`MGLAnnotationView`) + +If you're looking to add custom UIViews or have annotations that are dynamic or animatable, consider an `MGLAnnotationView` instead of an `MGLAnnotationImage` ([example](https://www.mapbox.com/ios-sdk/examples/annotation-views/)). + +Annotation views are a big advantage over annotation images when you need every annotation to be unique. For example, annotation views are ideal if as an example you want to show user locations on a map using their profile pictures. + +To use annotation views, you'll need to implement `MGLMapViewDelegate` `-mapView:viewForAnnotation` and provide a custom `MGLAnnotationView` (`UIView`) subclass. + +**Pros** + +* Custom, native UIViews +* No limit on style or image size +* Full support for animations +* Familiar API to MapKit +* Relative control over z-ordering using the `zPosition` property on `CALayer` + +**Cons** + +* Performance implications: + * UIViews are inherently slow to render compared to OpenGL, more apparent if you're adding many views or moving the map rapidly + * In some cases, you might consider runtime styling + +## Advanced: Runtime Styling + +If you're looking for absolute full control of how points are displayed on a map, consider [runtime styling](runtime-styling.html). + +You can use `MGLPointFeature` or any of the other [style feature subclasses](Style%20Features.html) to add points and shapes to an `MGLShapeSource`. + +From there, you can create one or many `MGLSymbolStyleLayer` or `MGLCircleStyleLayer` layers to filter and style points for display on the map ([example](https://www.mapbox.com/ios-sdk/examples/runtime-multiple-annotations)). + +**Pros** + +* Most powerful option +* Highest performance (rendered in GL directly) +* SDK-level support for labels rendered together with icons +* Finer control of z-ordering + * Rendering respects ordering within the data source + * Otherwise layers are lightweight so you can create a new layer for each level you need + +**Cons** + +* Currently you must implement your own tap gesture recognizer together with `MGLMapView.visibleFeaturesAtPoint` to recognize taps and manually show callouts ([example](https://www.mapbox.com/ios-sdk/examples/select-feature)). +* Currently no SDK support for animations. If you need animations, consider using an NSTimer and updating the layer properties accordingly. + diff --git a/platform/ios/docs/guides/Info.plist Keys.md b/platform/ios/docs/guides/Info.plist Keys.md new file mode 100644 index 0000000000..c5c7cf1d85 --- /dev/null +++ b/platform/ios/docs/guides/Info.plist Keys.md @@ -0,0 +1,21 @@ +# Info.plist Keys + +The Mapbox iOS SDK supports custom `Info.plist` keys in your application in order to configure various settings. + +## MGLMapboxAccessToken + +Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/) to be used by all instances of `MGLMapView` in the current application. + +Mapbox-hosted vector tiles and styles require an API access token, which you can obtain from the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). Access tokens associate requests to Mapbox’s vector tile and style APIs with your Mapbox account. They also deter other developers from using your styles without your permission. + +As an alternative, you can use `+[MGLAccountManager setAccessToken:]` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private. + +## MGLMapboxAPIBaseURL + +Use this key if you need to customize the API base URL used throughout the SDK. If unset, the default Mapbox API is used. + +The default value is `https://api.mapbox.com`. + +## MGLMapboxMetricsEnabledSettingShownInApp + +If you have implemented custom opt-out of Mapbox Telemetry within the user interface of your app, use this key to disable the built-in check for opt-out support. See [this guide](https://www.mapbox.com/ios-sdk/#telemetry_opt_out) for more details. diff --git a/platform/ios/docs/guides/Runtime Styling.md b/platform/ios/docs/guides/Runtime Styling.md new file mode 100644 index 0000000000..afc2ccae87 --- /dev/null +++ b/platform/ios/docs/guides/Runtime Styling.md @@ -0,0 +1,57 @@ +# Runtime Styling + +Mapbox's runtime styling features allow you direct control over every layer in your maps with code. It's now possible create dynamic maps and visualizations that aren't possible with other mobile maps SDKs. + +Runtime styling expands upon the design power of [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) and exposes all of the same properties and attributes directly to mobile developers in our SDK. + +Beyond the custom styled maps that you can create with Mapbox Studio, you can now change the look and feel of your map on the fly having maps in your app visually respond to user interaction or or context. Or leverage the power of OpenGL for highly performant and complex data visualizations. Now it's possible to mix in your own data and bring your map to life. + +## Example use cases + +As an example of what's possible with runtime styling, consider some of the following use cases: + +### Styling maps on the fly + +At runtime, you can tailor the map specifically to your user interface. Tweak colors, text, and icons to match the style to your brand. + +![dynamic styles](img/runtime-styling/DynamicStyles.gif "an example showing dynamic styles") + +For maps that aren't going to change in response to custom data or user interaction, consider creating a custom map style with [Mapbox Studio](https://www.mapbox.com/mapbox-studio/). + +### Map interactivity + +You can customize the map to the point of having it respond dynamically based on the actions your users are taking. Increase the text size of streets while a user is driving, emphasize points of interest tailored to a user's preferences, or change your UI if users are at parks, trails, landmarks, or rivers. + +![emojis](img/runtime-styling/Emoji.gif "an example showing emoji interaction") + +### Powerful data visualization + +Mapbox maps are built on top of OpenGL and can support rendering data without the traditional overhead of `UIView`-based map annotations. + +Mapbox can support data visualizations that were slow or impossible with traditional map SDKs. Render heatmaps, visualize population density, or even go so far as updating the snow levels in the mountains to match recent snowfall. + +![hex bins](img/runtime-styling/HexBins.gif "an example using hex bins") +![population](img/runtime-styling/Population.gif "an example showing population density") +![snow levels](img/runtime-styling/SnowLevels.gif "an example visualizing snow levels in the mountains") + +### Powerful annotations + +The Mapbox SDK gives you access to all of the same tools we use to render our default map styles. Instead of using generic pin markers, enrich your place data or custom polygons with icons and labels that make your maps stand out. + +![custom annotations](img/runtime-styling/CustomAnnotations.gif "an example showing custom annotations") + +### Custom shapes + +Draw custom shapes on the map the same way you would a custom `UIView` or `CALayer`. These shapes keep their geographic scale and are perfect for visualizing everything from indoor floor plans to metro systems to hurricane tracks. + + + + + +## Resources + +* [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) +* [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) +* [iOS code examples](https://www.mapbox.com/ios-sdk/examples/) + +Contact support@mapbox.com with futher questions about how to leverage runtime styling. diff --git a/platform/ios/docs/guides/Working with Mapbox Studio.md b/platform/ios/docs/guides/Working with Mapbox Studio.md new file mode 100644 index 0000000000..97aa614c41 --- /dev/null +++ b/platform/ios/docs/guides/Working with Mapbox Studio.md @@ -0,0 +1,97 @@ +# Working with Mapbox Studio + +[Mapbox Studio](http://mapbox.com/studio) is Mapbox's tool for creating custom map styles. It also serves as an excellent tool for rapidly prototyping dynamic maps and runtime styling interactions for iOS. + +## Creating a base style + +Start by heading to [mapbox.com/studio](http://mapbox.com/studio) and creating a new style. Any style that's close to what you'll be using in your app is ideal. + +## Prototyping with data + +The goal in using Mapbox Studio for prototyping runtime styling implementations is to test data presentation assumptions as quickly as possible. With the Mapbox Studio tools, you can import a small subset of your own real data, fake data as a placeholder, or prototype with existing Mapbox data. + +### Prototyping with Mapbox data +The default [Mapbox Streets tileset](https://www.mapbox.com/studio/tilesets/mapbox.mapbox-streets-v7/) might offer data similar to your own that you can use to style before you swap in your own data at runtime. + +For example, if you're looking to prototype points of interest, consider the `poi_label` layer; if you want to style GPS traces, the `roads` layer might be a good proxy. Take a look at what's available in [Mapbox Streets](https://www.mapbox.com/studio/tilesets/mapbox.mapbox-streets-v7/): there's probably a layer that closely matches your data. + +### Importing real data +If you can't find a good approximation for your data in Mapbox Streets, consider uploading a small subset of your data into Mapbox Studio as a custom tileset. + +From the [Mapbox Studio Dashboard](https://www.mapbox.com/studio/), click `Tilesets` in the sidebar, then click `New Tileset` to get started with most common geo file formats including KML, GPX, GeoJSON, Shapefiles, and CSV. + +### Faking placeholder data +If you don't have any custom data on hand in a format that works easily with the Tileset importer, you can fake placeholder data with the Dataset Editor. + +From the [Mapbox Studio Dashboard](https://www.mapbox.com/studio/), click `Datasets` in the sidebar, then click on `New Dataset` to get started. + +Zoom into your desired location and use the draw tools on the left to start creating a set of sample data. + +![create shapes](img/studio-workflow/create-polygons.gif) + +Next, add data properties you'd like to use to drive your style. Consider categorical properties or numeric properties that you'd use to filter and group your data. Text properties can be used to display icons or labels. + +![add properties](img/studio-workflow/add-properties.gif) + +**General Guidelines:** + +* Text along a line: add line with a text property +* Text at specific points on a line or polygon: in addition to the line, create points at the specific points you'd like with text properties +* If you want circles where scale doesn't matter relative to the geography (e.g. always 20 pixels), you can add as a point and style with a circle layer or a symbol +* If you want circles or arcs where the scale matters (e.g. 10 mile radius), you'll need to approximately freehand a polygon, and you can create more precisely later in code. + +When you're done, save your dataset and export as a tileset. When that's complete, add your tileset to your style. + +### Import into your style + +1. Click `New Layer` +2. Select your tileset +3. Select your shape type: + * `Symbol`: best for text and icons + * `Line`: best for lines or adding strokes to polygons + * `Fill`: best for filling polygons + * `Circle`: for styling points or nodes along a line or polygon as circles. If you need circles of a fixed radius (e.g. 1 mile radius), you should model your data as a polygon. +4. Add filters if necessary + * You can selectively filter your data by their properties to group and style separately +5. Click on `Create Layer` + +## Styling with Mapbox Studio + +Mapbox Studio shines for styling your data and the process is much faster than attempting to style natively. + +There are some nuances to understand between the different layer types and how they work together. Don't be afraid to use the layers sidebar to peek into the techniques used to style the stock Mapbox maps. You can duplicate these layers, re-point the source to your own data, and tweak as needed. + +**Best Practices:** + +* Layers are cheap, so duplicate and update filters liberally. +* If you'd like to stroke polygons you'll need to use two layers: one a fill and one a stroked line. +* If you want to stroke a line, create two layers, one for the default stroke and one with a wider width for its casing +* If you intend to animate properties or transition between values, consider creating separate layers for each state and toggling visibility to visualize the difference. + +## Implement on iOS with runtime styling + +Once you're happy with the styles you've created, it's time to [get setup with Mapbox in your app](https://www.mapbox.com/ios-sdk/). + +To implement your prototypes with runtime styling: + +1. Implement `MGLMapViewDelegate` `-mapView:didFinishLoadingStyle:` +2. Add your real data as a source + * This can be done using vector data from tileset editor ([example](https://www.mapbox.com/ios-sdk/examples/runtime-circle-styles)), custom vector tiles, added as GeoJSON ([example](https://www.mapbox.com/ios-sdk/examples/runtime-add-line), or added manually through the app via `MGLShapeSource` ([example](https://www.mapbox.com/ios-sdk/examples/runtime-multiple-annotations)) +3. For each layer you've prototyped in studio, add it's corresponding `MGLStyleLayer` subclass: `MGLSymbolStyleLayer`, `MGLLineStyleLayer`, `MGLFillStyleLayer`, or `MGLCircleStyleLayer`. + +**Translating style attributes from Studio** +For each property you've edited in Studio, you can hover over the property name to find it's corresponding property in the iOS SDK. They're generally the camelCased version of the Property ID. + +![property values](img/studio-workflow/property-values.png) + +**Translating stop functions** +It's possible to use stop functions in Mapbox Studio to transition the style of a layer by it's zoom level (e.g. a line that gets wider as you zoom in). These can be translated in the mobile SDKs using `+[MGLSyleValue valueWithInterpolationBase:stops:]`. The rate of change between stops in studio is represented by `interpolationBase`. + +![Stop functions](img/studio-workflow/stop-functions.png) + +## Resources + +* [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) +* [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) +* [iOS code examples](https://www.mapbox.com/ios-sdk/examples/) + diff --git a/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif b/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif new file mode 100644 index 0000000000..dee99d01fd Binary files /dev/null and b/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif differ diff --git a/platform/ios/docs/img/runtime-styling/DynamicStyles.gif b/platform/ios/docs/img/runtime-styling/DynamicStyles.gif new file mode 100644 index 0000000000..b42d30c602 Binary files /dev/null and b/platform/ios/docs/img/runtime-styling/DynamicStyles.gif differ diff --git a/platform/ios/docs/img/runtime-styling/Emoji.gif b/platform/ios/docs/img/runtime-styling/Emoji.gif new file mode 100644 index 0000000000..fc50b28972 Binary files /dev/null and b/platform/ios/docs/img/runtime-styling/Emoji.gif differ diff --git a/platform/ios/docs/img/runtime-styling/HexBins.gif b/platform/ios/docs/img/runtime-styling/HexBins.gif new file mode 100644 index 0000000000..c810085f22 Binary files /dev/null and b/platform/ios/docs/img/runtime-styling/HexBins.gif differ diff --git a/platform/ios/docs/img/runtime-styling/Population.gif b/platform/ios/docs/img/runtime-styling/Population.gif new file mode 100644 index 0000000000..81b6c6310f Binary files /dev/null and b/platform/ios/docs/img/runtime-styling/Population.gif differ diff --git a/platform/ios/docs/img/runtime-styling/SnowLevels.gif b/platform/ios/docs/img/runtime-styling/SnowLevels.gif new file mode 100644 index 0000000000..8ee2f9fddd Binary files /dev/null and b/platform/ios/docs/img/runtime-styling/SnowLevels.gif differ diff --git a/platform/ios/docs/img/screenshot.png b/platform/ios/docs/img/screenshot.png new file mode 100644 index 0000000000..62c04746d4 Binary files /dev/null and b/platform/ios/docs/img/screenshot.png differ diff --git a/platform/ios/docs/img/studio-workflow/add-properties.gif b/platform/ios/docs/img/studio-workflow/add-properties.gif new file mode 100644 index 0000000000..740fae655b Binary files /dev/null and b/platform/ios/docs/img/studio-workflow/add-properties.gif differ diff --git a/platform/ios/docs/img/studio-workflow/create-polygons.gif b/platform/ios/docs/img/studio-workflow/create-polygons.gif new file mode 100644 index 0000000000..6eb2c0afb8 Binary files /dev/null and b/platform/ios/docs/img/studio-workflow/create-polygons.gif differ diff --git a/platform/ios/docs/img/studio-workflow/property-values.png b/platform/ios/docs/img/studio-workflow/property-values.png new file mode 100644 index 0000000000..95704241f9 Binary files /dev/null and b/platform/ios/docs/img/studio-workflow/property-values.png differ diff --git a/platform/ios/docs/img/studio-workflow/stop-functions.png b/platform/ios/docs/img/studio-workflow/stop-functions.png new file mode 100644 index 0000000000..4affecf005 Binary files /dev/null and b/platform/ios/docs/img/studio-workflow/stop-functions.png differ diff --git a/platform/ios/docs/pod-README.md b/platform/ios/docs/pod-README.md index 78647b2603..b1a763bcf1 100644 --- a/platform/ios/docs/pod-README.md +++ b/platform/ios/docs/pod-README.md @@ -4,7 +4,7 @@ The Mapbox iOS SDK is an open-source framework for embedding interactive map vie For more information, check out the [Mapbox iOS SDK homepage](https://www.mapbox.com/ios-sdk/) and the [full changelog](https://github.com/mapbox/mapbox-gl-native/blob/master/platform/ios/CHANGELOG.md) online. -[![](https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/platform/ios/screenshot.png)]() +[![](https://raw.githubusercontent.com/mapbox/mapbox-gl-native/master/platform/ios/docs/img/screenshot.png)]() ## Installation diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 7d8d82988d..1f1e48fce5 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -15,6 +15,9 @@ hide_documentation_coverage: Yes custom_categories: - name: Guides children: + - Adding Points to a Map + - Runtime Styling + - Working with Mapbox Studio - Info.plist Keys - name: Maps children: diff --git a/platform/ios/screenshot.png b/platform/ios/screenshot.png deleted file mode 100644 index 62c04746d4..0000000000 Binary files a/platform/ios/screenshot.png and /dev/null differ diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index 78eb5121eb..634f4de5dc 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -30,7 +30,7 @@ sed -n -e '/^## /{' -e ':a' -e 'n' -e '/^## /q' -e 'p' -e 'ba' -e '}' platform/i rm -rf ${OUTPUT} mkdir -p ${OUTPUT} -cp platform/ios/screenshot.png "${OUTPUT}" +cp -r platform/ios/docs/img "${OUTPUT}/img" DEFAULT_THEME="platform/darwin/docs/theme" THEME=${JAZZY_THEME:-$DEFAULT_THEME} @@ -46,7 +46,7 @@ jazzy \ --framework-root ${FRAMEWORK_PATH} \ --umbrella-header "${FRAMEWORK_PATH}/Headers/Mapbox.h" \ --readme ${README} \ - --documentation="platform/ios/docs/Info.plist Keys.md" \ + --documentation="platform/ios/docs/guides/*.md" \ --root-url https://www.mapbox.com/ios-sdk/api/${RELEASE_VERSION}/ \ --theme ${THEME} \ --output ${OUTPUT} -- cgit v1.2.1 From e6132d248b54d202c3fa132b3084660a0bbe3c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 26 Dec 2016 14:24:05 -0800 Subject: [ios, macos] Rewrote predicate/filter conversion When converting predicates to filters, symmetric comparison predicates can now compare a value to a key in addition to the usual key-to-value order. Added error checking for unhandled combinations like key-to-key. Fixed a crash converting a CONTAINS predicate into a filter. Added support for constant value expressions inside aggregate expressions. Allow sets as aggregate expressions just like arrays, except in BETWEEN predicates where order matters. Flatten NOT predicates into more specialized filters. When converting filters to predicates, use constant value expressions inside aggregate expressions. Convert to a BETWEEN predicate when possible. Replaced predicate round-tripping integration tests with systematic unit tests for converting in either direction, plus unit tests for round-tripping and symmetry. Refined exception names and messages. Realphabetized files in groups. --- .../src/NSComparisonPredicate+MGLAdditions.mm | 212 ++++++++--- .../darwin/src/NSCompoundPredicate+MGLAdditions.mm | 53 ++- platform/darwin/src/NSExpression+MGLAdditions.mm | 25 +- platform/darwin/src/NSPredicate+MGLAdditions.mm | 75 +++- platform/darwin/test/MGLFilterTests.mm | 194 ---------- platform/darwin/test/MGLPredicateTests.mm | 416 +++++++++++++++++++++ platform/ios/ios.xcodeproj/project.pbxproj | 15 +- platform/macos/macos.xcodeproj/project.pbxproj | 12 +- 8 files changed, 696 insertions(+), 306 deletions(-) delete mode 100644 platform/darwin/test/MGLFilterTests.mm create mode 100644 platform/darwin/test/MGLPredicateTests.mm (limited to 'platform') diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm index 19c264aa40..58390b0b81 100644 --- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm @@ -7,95 +7,189 @@ - (mbgl::style::Filter)mgl_filter { + NSExpression *leftExpression = self.leftExpression; + NSExpression *rightExpression = self.rightExpression; + NSExpressionType leftType = leftExpression.expressionType; + NSExpressionType rightType = rightExpression.expressionType; + BOOL isReversed = ((leftType == NSConstantValueExpressionType || leftType == NSAggregateExpressionType) + && rightType == NSKeyPathExpressionType); switch (self.predicateOperatorType) { case NSEqualToPredicateOperatorType: { - if (self.rightExpression.constantValue) - { - auto filter = mbgl::style::EqualsFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; - } - else - { - auto filter = mbgl::style::NotHasFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - return filter; + mbgl::style::EqualsFilter eqFilter; + eqFilter.key = self.mgl_keyPath.UTF8String; + eqFilter.value = self.mgl_constantValue; + + // Convert == nil to NotHasFilter. + if (eqFilter.value.is()) { + mbgl::style::NotHasFilter notHasFilter; + notHasFilter.key = eqFilter.key; + return notHasFilter; } + + return eqFilter; } case NSNotEqualToPredicateOperatorType: { - if (self.rightExpression.constantValue) - { - auto filter = mbgl::style::NotEqualsFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; - } - else - { - auto filter = mbgl::style::HasFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - return filter; + mbgl::style::NotEqualsFilter neFilter; + neFilter.key = self.mgl_keyPath.UTF8String; + neFilter.value = self.mgl_constantValue; + + // Convert != nil to HasFilter. + if (neFilter.value.is()) { + mbgl::style::HasFilter hasFilter; + hasFilter.key = neFilter.key; + return hasFilter; } + + return neFilter; } case NSGreaterThanPredicateOperatorType: { - auto filter = mbgl::style::GreaterThanFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; + if (isReversed) { + mbgl::style::LessThanFilter ltFilter; + ltFilter.key = self.mgl_keyPath.UTF8String; + ltFilter.value = self.mgl_constantValue; + return ltFilter; + } else { + mbgl::style::GreaterThanFilter gtFilter; + gtFilter.key = self.mgl_keyPath.UTF8String; + gtFilter.value = self.mgl_constantValue; + return gtFilter; + } } case NSGreaterThanOrEqualToPredicateOperatorType: { - auto filter = mbgl::style::GreaterThanEqualsFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; + if (isReversed) { + mbgl::style::LessThanEqualsFilter lteFilter; + lteFilter.key = self.mgl_keyPath.UTF8String; + lteFilter.value = self.mgl_constantValue; + return lteFilter; + } else { + mbgl::style::GreaterThanEqualsFilter gteFilter; + gteFilter.key = self.mgl_keyPath.UTF8String; + gteFilter.value = self.mgl_constantValue; + return gteFilter; + } } case NSLessThanPredicateOperatorType: { - auto filter = mbgl::style::LessThanFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; + if (isReversed) { + mbgl::style::GreaterThanFilter gtFilter; + gtFilter.key = self.mgl_keyPath.UTF8String; + gtFilter.value = self.mgl_constantValue; + return gtFilter; + } else { + mbgl::style::LessThanFilter ltFilter; + ltFilter.key = self.mgl_keyPath.UTF8String; + ltFilter.value = self.mgl_constantValue; + return ltFilter; + } } case NSLessThanOrEqualToPredicateOperatorType: { - auto filter = mbgl::style::LessThanEqualsFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.value = self.rightExpression.mgl_filterValue; - return filter; + if (isReversed) { + mbgl::style::GreaterThanEqualsFilter gteFilter; + gteFilter.key = self.mgl_keyPath.UTF8String; + gteFilter.value = self.mgl_constantValue; + return gteFilter; + } else { + mbgl::style::LessThanEqualsFilter lteFilter; + lteFilter.key = self.mgl_keyPath.UTF8String; + lteFilter.value = self.mgl_constantValue; + return lteFilter; + } } case NSInPredicateOperatorType: { - auto filter = mbgl::style::InFilter(); - filter.key = self.leftExpression.keyPath.UTF8String; - filter.values = self.rightExpression.mgl_filterValues; - return filter; + if (isReversed) { + if (leftType == NSConstantValueExpressionType && [leftExpression.constantValue isKindOfClass:[NSString class]]) { + [NSException raise:NSInvalidArgumentException + format:@"CONTAINS not supported for string comparison."]; + } + [NSException raise:NSInvalidArgumentException + format:@"Predicate cannot compare values IN attribute."]; + } + mbgl::style::InFilter inFilter; + inFilter.key = leftExpression.keyPath.UTF8String; + inFilter.values = rightExpression.mgl_filterValues; + return inFilter; } case NSContainsPredicateOperatorType: { - auto filter = mbgl::style::InFilter(); - filter.key = [self.rightExpression.constantValue UTF8String]; - filter.values = self.leftExpression.mgl_filterValues; - return filter; + if (!isReversed) { + if (rightType == NSConstantValueExpressionType && [rightExpression.constantValue isKindOfClass:[NSString class]]) { + [NSException raise:NSInvalidArgumentException + format:@"IN not supported for string comparison."]; + } + [NSException raise:NSInvalidArgumentException + format:@"Predicate cannot compare attribute CONTAINS values."]; + } + mbgl::style::InFilter inFilter; + inFilter.key = rightExpression.keyPath.UTF8String; + inFilter.values = leftExpression.mgl_filterValues; + return inFilter; } case NSBetweenPredicateOperatorType: { - auto filter = mbgl::style::AllFilter(); - auto gteFilter = mbgl::style::GreaterThanEqualsFilter(); - gteFilter.key = self.leftExpression.keyPath.UTF8String; - gteFilter.value = self.rightExpression.mgl_filterValues[0]; - filter.filters.push_back(gteFilter); - auto lteFilter = mbgl::style::LessThanEqualsFilter(); - lteFilter.key = self.leftExpression.keyPath.UTF8String; - lteFilter.value = self.rightExpression.mgl_filterValues[1]; - filter.filters.push_back(lteFilter); - return filter; + if (isReversed) { + [NSException raise:NSInvalidArgumentException + format:@"Predicate cannot compare bounds BETWEEN attribute."]; + } + if (![rightExpression.constantValue isKindOfClass:[NSArray class]]) { + [NSException raise:NSInvalidArgumentException + format:@"Right side of BETWEEN predicate must be an array."]; // not NSSet + } + auto values = rightExpression.mgl_filterValues; + if (values.size() != 2) { + [NSException raise:NSInvalidArgumentException + format:@"Right side of BETWEEN predicate must have two items."]; + } + mbgl::style::AllFilter allFilter; + mbgl::style::GreaterThanEqualsFilter gteFilter; + gteFilter.key = leftExpression.keyPath.UTF8String; + gteFilter.value = values[0]; + allFilter.filters.push_back(gteFilter); + mbgl::style::LessThanEqualsFilter lteFilter; + lteFilter.key = leftExpression.keyPath.UTF8String; + lteFilter.value = values[1]; + allFilter.filters.push_back(lteFilter); + return allFilter; } case NSMatchesPredicateOperatorType: case NSLikePredicateOperatorType: case NSBeginsWithPredicateOperatorType: case NSEndsWithPredicateOperatorType: case NSCustomSelectorPredicateOperatorType: - [NSException raise:@"Unsupported operator type" + [NSException raise:NSInvalidArgumentException format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType]; } return {}; } +- (NSString *)mgl_keyPath { + NSExpression *leftExpression = self.leftExpression; + NSExpression *rightExpression = self.rightExpression; + NSExpressionType leftType = leftExpression.expressionType; + NSExpressionType rightType = rightExpression.expressionType; + if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) { + return leftExpression.keyPath; + } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) { + return rightExpression.keyPath; + } + + [NSException raise:NSInvalidArgumentException + format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."]; + return nil; +} + +- (mbgl::Value)mgl_constantValue { + NSExpression *leftExpression = self.leftExpression; + NSExpression *rightExpression = self.rightExpression; + NSExpressionType leftType = leftExpression.expressionType; + NSExpressionType rightType = rightExpression.expressionType; + mbgl::Value value; + if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) { + value = rightExpression.mgl_filterValue; + } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) { + value = leftExpression.mgl_filterValue; + } else { + [NSException raise:NSInvalidArgumentException + format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."]; + } + return value; +} + @end diff --git a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm index 07114308c9..2697467198 100644 --- a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm @@ -18,32 +18,49 @@ { switch (self.compoundPredicateType) { case NSNotPredicateType: { + NSAssert(self.subpredicates.count <= 1, @"NOT predicate cannot have multiple subpredicates."); + NSPredicate *subpredicate = self.subpredicates.firstObject; + mbgl::style::Filter subfilter = subpredicate.mgl_filter; - // Translate a nested NSComparisonPredicate with operator type NSInPredicateOperatorType into a flat mbgl::NotIn filter. - NSArray *comparisonPredicates = [self.subpredicates filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"class == %@", [NSComparisonPredicate class]]]; - NSArray *notInPredicates = [comparisonPredicates filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSComparisonPredicate *_Nonnull predicate, NSDictionary * _Nullable bindings) { - return predicate.predicateOperatorType == NSInPredicateOperatorType; - }]]; + // Convert NOT(!= nil) to NotHasFilter. + if (subfilter.is()) { + auto hasFilter = subfilter.get(); + return mbgl::style::NotHasFilter { .key = hasFilter.key }; + } + + // Convert NOT(== nil) to HasFilter. + if (subfilter.is()) { + auto hasFilter = subfilter.get(); + return mbgl::style::HasFilter { .key = hasFilter.key }; + } + + // Convert NOT(IN) or NOT(CONTAINS) to NotInFilter. + if (subfilter.is()) { + auto inFilter = subfilter.get(); + mbgl::style::NotInFilter notInFilter; + notInFilter.key = inFilter.key; + notInFilter.values = inFilter.values; + return notInFilter; + } - if (notInPredicates.count) { - auto filter = mbgl::style::NotInFilter(); - filter.key = notInPredicates.firstObject.leftExpression.keyPath.UTF8String; - filter.values = notInPredicates.firstObject.rightExpression.mgl_filterValues; - return filter; - } else { - auto filter = mbgl::style::NoneFilter(); - filter.filters = [self mgl_subfilters]; - return filter; + // Convert NOT(), NOT(AND), NOT(NOT), NOT(==), etc. into NoneFilter. + mbgl::style::NoneFilter noneFilter; + if (subfilter.is()) { + // Flatten NOT(OR). + noneFilter.filters = subfilter.get().filters; + } else if (subpredicate) { + noneFilter.filters = { subfilter }; } + return noneFilter; } case NSAndPredicateType: { - auto filter = mbgl::style::AllFilter(); - filter.filters = [self mgl_subfilters]; + mbgl::style::AllFilter filter; + filter.filters = self.mgl_subfilters; return filter; } case NSOrPredicateType: { - auto filter = mbgl::style::AnyFilter(); - filter.filters = [self mgl_subfilters]; + mbgl::style::AnyFilter filter; + filter.filters = self.mgl_subfilters; return filter; } } diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 6af069487e..97f3e11dba 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -4,15 +4,19 @@ - (std::vector)mgl_filterValues { - if ([self.constantValue isKindOfClass:NSArray.class]) { - NSArray *values = self.constantValue; - std::vectorconvertedValues; - for (id value in values) { - convertedValues.push_back([self mgl_convertedValueWithValue:value]); + if ([self.constantValue isKindOfClass:[NSArray class]] || [self.constantValue isKindOfClass:[NSSet class]]) { + std::vector convertedValues; + for (id item in self.constantValue) { + id constantValue = item; + if ([item isKindOfClass:[NSExpression class]]) { + constantValue = [constantValue constantValue]; + } + convertedValues.push_back([self mgl_convertedValueWithValue:constantValue]); } return convertedValues; } - [NSException raise:@"Values not handled" format:@""]; + [NSException raise:NSInvalidArgumentException + format:@"Constant value expression must contain an array or set."]; return { }; } @@ -42,7 +46,10 @@ // We still do this conversion in order to provide a valid value. static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - NSLog(@"One-time warning: Float values are converted to double and can introduce imprecision; please use double values explicitly in predicate arguments."); + NSLog(@"Float value in expression will be converted to a double; some imprecision may result. " + @"Use double values explicitly when specifying constant expression values and " + @"when specifying arguments to predicate and expression format strings. " + @"This will be logged only once."); }); return { (double)number.doubleValue }; } else if ([number compare:@(0)] == NSOrderedDescending || @@ -55,8 +62,8 @@ // We use long long here to avoid any truncation. return { (int64_t)number.longLongValue }; } - } else if (value != [NSNull null]) { - [NSException raise:@"Value not handled" + } else if (value && value != [NSNull null]) { + [NSException raise:NSInvalidArgumentException format:@"Can’t convert %s:%@ to mbgl::Value", [value objCType], value]; } return { }; diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index 64ad277e4d..f999df96b0 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -16,7 +16,8 @@ public: NSArray* getValues(std::vector values) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()]; for (auto value : values) { - [array addObject:mbgl::Value::visit(value, ValueEvaluator())]; + id constantValue = mbgl::Value::visit(value, ValueEvaluator()); + [array addObject:[NSExpression expressionForConstantValue:constantValue]]; } return array; } @@ -58,20 +59,64 @@ public: } NSPredicate* operator()(mbgl::style::AnyFilter filter) { - return [NSCompoundPredicate orPredicateWithSubpredicates:getPredicates(filter.filters)]; + NSArray *subpredicates = getPredicates(filter.filters); + if (subpredicates.count) { + return [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates]; + } + return [NSPredicate predicateWithValue:NO]; } NSPredicate* operator()(mbgl::style::AllFilter filter) { - return [NSCompoundPredicate andPredicateWithSubpredicates:getPredicates(filter.filters)]; + // Convert [all, [>=, key, lower], [<=, key, upper]] to key BETWEEN {lower, upper} + if (filter.filters.size() == 2) { + auto leftFilter = filter.filters[0]; + auto rightFilter = filter.filters[1]; + + std::string lowerKey; + std::string upperKey; + mbgl::Value lowerBound; + mbgl::Value upperBound; + if (leftFilter.is()) { + lowerKey = leftFilter.get().key; + lowerBound = leftFilter.get().value; + } else if (rightFilter.is()) { + lowerKey = rightFilter.get().key; + lowerBound = rightFilter.get().value; + } + + if (leftFilter.is()) { + upperKey = leftFilter.get().key; + upperBound = leftFilter.get().value; + } else if (rightFilter.is()) { + upperKey = rightFilter.get().key; + upperBound = rightFilter.get().value; + } + + if (!lowerBound.is() && !upperBound.is() + && lowerKey == upperKey) { + return [NSPredicate predicateWithFormat:@"%K BETWEEN {%@, %@}", + @(lowerKey.c_str()), + mbgl::Value::visit(lowerBound, ValueEvaluator()), + mbgl::Value::visit(upperBound, ValueEvaluator())]; + } + } + + NSArray *subpredicates = getPredicates(filter.filters); + if (subpredicates.count) { + return [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates]; + } + return [NSPredicate predicateWithValue:YES]; } NSPredicate* operator()(mbgl::style::NoneFilter filter) { - NSArray *predicates = getPredicates(filter.filters); - if (predicates.count > 1) { - NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; + NSArray *subpredicates = getPredicates(filter.filters); + if (subpredicates.count > 1) { + NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates]; return [NSCompoundPredicate notPredicateWithSubpredicate:predicate]; + } else if (subpredicates.count) { + return [NSCompoundPredicate notPredicateWithSubpredicate:subpredicates.firstObject]; } else { - return [NSCompoundPredicate notPredicateWithSubpredicate:predicates.firstObject]; + return [NSPredicate predicateWithValue:YES]; } } @@ -91,18 +136,22 @@ public: { if ([self isEqual:[NSPredicate predicateWithValue:YES]]) { - auto filter = mbgl::style::AllFilter(); - return filter; + return mbgl::style::AllFilter(); } if ([self isEqual:[NSPredicate predicateWithValue:NO]]) { - auto filter = mbgl::style::AnyFilter(); - return filter; + return mbgl::style::AnyFilter(); + } + + if ([self.predicateFormat hasPrefix:@"BLOCKPREDICATE("]) + { + [NSException raise:NSInvalidArgumentException + format:@"Block-based predicates are not supported."]; } - [NSException raise:@"Not supported" - format:@"Try with NSComparisonPredicate or NSCompoundPredicate instead."]; + [NSException raise:NSInvalidArgumentException + format:@"Unrecognized predicate type."]; return {}; } diff --git a/platform/darwin/test/MGLFilterTests.mm b/platform/darwin/test/MGLFilterTests.mm deleted file mode 100644 index e688d50583..0000000000 --- a/platform/darwin/test/MGLFilterTests.mm +++ /dev/null @@ -1,194 +0,0 @@ -#import "MGLStyleLayerTests.h" - -#import "NSPredicate+MGLAdditions.h" -#import "MGLValueEvaluator.h" - - -@interface MGLFilterTests : MGLStyleLayerTests { - MGLShapeSource *source; - MGLLineStyleLayer *layer; -} -@end - -@implementation MGLFilterTests - -- (void)setUp -{ - [super setUp]; - NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; - NSURL *url = [NSURL fileURLWithPath:filePath]; - NSData *geoJSONData = [NSData dataWithContentsOfURL:url]; - NSError *error; - MGLShape *shape = [MGLShape shapeWithData:geoJSONData encoding:NSUTF8StringEncoding error:&error]; - XCTAssertNil(error); - XCTAssertNotNil(shape); - source = [[MGLShapeSource alloc] initWithIdentifier:@"test-source" shape:shape options:nil]; - [self.mapView.style addSource:source]; - layer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"test-layer" source:source]; -} - -- (void)tearDown -{ - [self.mapView.style removeLayer:layer]; - [self.mapView.style removeSource:source]; -} - -- (NSArray *)predicates -{ - NSPredicate *equalPredicate = [NSPredicate predicateWithFormat:@"type == 'neighbourhood'"]; - NSPredicate *notEqualPredicate = [NSPredicate predicateWithFormat:@"type != 'park'"]; - NSPredicate *greaterThanPredicate = [NSPredicate predicateWithFormat:@"%K > %@", @"stroke-width", @2.1]; - NSPredicate *greaterThanOrEqualToPredicate = [NSPredicate predicateWithFormat:@"%K >= %@", @"stroke-width", @2.1]; - NSPredicate *lessThanOrEqualToPredicate = [NSPredicate predicateWithFormat:@"%K <= %@", @"stroke-width", @2.1]; - NSPredicate *lessThanPredicate = [NSPredicate predicateWithFormat:@"%K < %@", @"stroke-width", @2.1]; - NSPredicate *inPredicate = [NSPredicate predicateWithFormat:@"type IN %@", @[@"park", @"neighbourhood"]]; - NSPredicate *notInPredicate = [NSPredicate predicateWithFormat:@"NOT (type IN %@)", @[@"park", @"neighbourhood"]]; - NSPredicate *inNotInPredicate = [NSPredicate predicateWithFormat:@"type IN %@ AND NOT (type IN %@)", @[@"park"], @[@"neighbourhood", @"test"]]; - NSPredicate *typePredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"$type", @"Feature"]; - NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"$id", @"1234123"]; - NSPredicate *specialCharsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"ty-’pè", @"sŒm-ethįng"]; - NSPredicate *booleanPredicate = [NSPredicate predicateWithFormat:@"cluster != YES"]; - NSPredicate *nilEqualsPredicate = [NSPredicate predicateWithFormat:@"type == %@", nil]; - NSPredicate *nilNotEqualsPredicate = [NSPredicate predicateWithFormat:@"type != %@", nil]; - return @[ - equalPredicate, - notEqualPredicate, - greaterThanPredicate, - greaterThanOrEqualToPredicate, - lessThanOrEqualToPredicate, - lessThanPredicate, - inPredicate, - notInPredicate, - inNotInPredicate, - typePredicate, - idPredicate, - specialCharsPredicate, - booleanPredicate, - nilEqualsPredicate, - nilNotEqualsPredicate - ]; -} - -- (void)testAllPredicates -{ - for (NSPredicate *predicate in self.predicates) { - layer.predicate = predicate; - XCTAssertEqualObjects(layer.predicate, predicate); - } - [self.mapView.style addLayer:layer]; -} - -- (void)testContainsPredicate -{ - // core does not have a "contains" filter but we can achieve the equivalent by creating an `mbgl::style::InFilter` - // and searching the value for the key - NSPredicate *expectedPredicate = [NSPredicate predicateWithFormat:@"park IN %@", @[@"park", @"neighbourhood"]]; - NSPredicate *containsPredicate = [NSPredicate predicateWithFormat:@"%@ CONTAINS %@", @[@"park", @"neighbourhood"], @"park"]; - - layer.predicate = containsPredicate; - XCTAssertEqualObjects(layer.predicate, expectedPredicate); - [self.mapView.style addLayer:layer]; -} - -- (void)testBetweenPredicate -{ - // core does not have a "between" filter but we can achieve the equivalent by creating a set of greater than or equal / less than or equal - // filters for the lower and upper bounds (inclusive) - NSPredicate *expectedPredicate = [NSCompoundPredicate predicateWithFormat:@"%K >= 2 AND %K <= 3", @"stroke-width", @"stroke-width"]; - NSPredicate *betweenPredicate = [NSPredicate predicateWithFormat:@"%K BETWEEN %@", @"stroke-width", @[@2.0, @3.0]]; - - layer.predicate = betweenPredicate; - XCTAssertEqualObjects(layer.predicate, expectedPredicate); - [self.mapView.style addLayer:layer]; -} - -- (void)testTruePredicate -{ - // This comes out of the class cluster as an NSTruePredicate and it is equal to `[NSPredicate predicateWithValue:YES]` - NSPredicate *truePredicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"]; - - layer.predicate = truePredicate; - XCTAssertEqualObjects(layer.predicate.description, truePredicate.description); - [self.mapView.style addLayer:layer]; -} - -- (void)testFalsePredicate -{ - // This comes out of the class cluster as an NSFalsePredicate and it is equal to `[NSPredicate predicateWithValue:NO]` - NSPredicate *falsePredicate = [NSPredicate predicateWithFormat:@"FALSEPREDICATE"]; - - layer.predicate = falsePredicate; - XCTAssertEqualObjects(layer.predicate.description, falsePredicate.description); - [self.mapView.style addLayer:layer]; -} - -- (void)testIntermittentEncoding -{ - NSPredicate *specialCharsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"ty-’pè", @"sŒm-ethįng"]; - layer.predicate = specialCharsPredicate; - - NSComparisonPredicate *getPredicate = (NSComparisonPredicate *)layer.predicate; - mbgl::style::EqualsFilter filter = layer.predicate.mgl_filter.get(); - - id objcKey = getPredicate.leftExpression.keyPath; - id cppKey = @(filter.key.c_str()); - id objcValue = mbgl::Value::visit(getPredicate.rightExpression.mgl_filterValue, ValueEvaluator()); - id cppValue = mbgl::Value::visit(filter.value, ValueEvaluator()); - - XCTAssertEqualObjects(objcKey, cppKey); - XCTAssertEqualObjects(objcValue, cppValue); - - [self.mapView.style addLayer:layer]; -} - -- (void)testNestedFilters -{ - NSPredicate *equalPredicate = [NSPredicate predicateWithFormat:@"type == 'neighbourhood'"]; - NSPredicate *notEqualPredicate = [NSPredicate predicateWithFormat:@"type != 'park'"]; - - NSPredicate *allPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[equalPredicate, notEqualPredicate]]; - NSPredicate *anyPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[equalPredicate, notEqualPredicate]]; - - layer.predicate = allPredicate; - XCTAssertEqualObjects(layer.predicate, allPredicate); - layer.predicate = anyPredicate; - XCTAssertEqualObjects(layer.predicate, anyPredicate); - - [self.mapView.style addLayer:layer]; -} - -- (void)testAndPredicates -{ - NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:self.predicates]; - layer.predicate = predicate; - XCTAssertEqualObjects(predicate, layer.predicate); - [self.mapView.style addLayer:layer]; -} - -- (void)testOrPredicates -{ - NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:self.predicates]; - layer.predicate = predicate; - XCTAssertEqualObjects(predicate, layer.predicate); - [self.mapView.style addLayer:layer]; -} - -- (void)testNotAndPredicates -{ - NSPredicate *predicates = [NSCompoundPredicate andPredicateWithSubpredicates:self.predicates]; - NSCompoundPredicate *predicate = [NSCompoundPredicate notPredicateWithSubpredicate:predicates]; - layer.predicate = predicate; - XCTAssertEqualObjects(predicate, layer.predicate); - [self.mapView.style addLayer:layer]; -} - -- (void)testNotOrPredicates -{ - NSPredicate *predicates = [NSCompoundPredicate orPredicateWithSubpredicates:self.predicates]; - NSCompoundPredicate *predicate = [NSCompoundPredicate notPredicateWithSubpredicate:predicates]; - layer.predicate = predicate; - XCTAssertEqualObjects(predicate, layer.predicate); - [self.mapView.style addLayer:layer]; -} - -@end diff --git a/platform/darwin/test/MGLPredicateTests.mm b/platform/darwin/test/MGLPredicateTests.mm new file mode 100644 index 0000000000..07466dfd13 --- /dev/null +++ b/platform/darwin/test/MGLPredicateTests.mm @@ -0,0 +1,416 @@ +#import +#import + +#import "NSPredicate+MGLAdditions.h" +#import "MGLValueEvaluator.h" + +namespace mbgl { + namespace style { + bool operator!=(const Filter &a, const Filter &b) { + return !(a == b); + } + } +} + +#define MGLAssertEqualFilters(actual, expected, ...) \ + XCTAssertTrue(actual.is<__typeof__(expected)>()); \ + if (actual.is<__typeof__(expected)>()) { \ + XCTAssertEqual(actual.get<__typeof__(expected)>(), expected, __VA_ARGS__); \ + } + +@interface MGLPredicateTests : XCTestCase +@end + +@implementation MGLPredicateTests + +- (void)testFilterization { + { + auto actual = [NSPredicate predicateWithValue:YES].mgl_filter; + mbgl::style::AllFilter expected; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithValue:NO].mgl_filter; + mbgl::style::AnyFilter expected; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a = 'b'"].mgl_filter; + mbgl::style::EqualsFilter expected = { .key = "a", .value = std::string("b") }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a = nil"].mgl_filter; + mbgl::style::NotHasFilter expected = { .key = "a" }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a != 'b'"].mgl_filter; + mbgl::style::NotEqualsFilter expected = { .key = "a", .value = std::string("b") }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a != nil"].mgl_filter; + mbgl::style::HasFilter expected = { .key = "a" }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a < 'b'"].mgl_filter; + mbgl::style::LessThanFilter expected = { .key = "a", .value = std::string("b") }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a <= 'b'"].mgl_filter; + mbgl::style::LessThanEqualsFilter expected = { .key = "a", .value = std::string("b") }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a > 'b'"].mgl_filter; + mbgl::style::GreaterThanFilter expected = { .key = "a", .value = std::string("b") }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a >= 'b'"].mgl_filter; + mbgl::style::GreaterThanEqualsFilter expected = { .key = "a", .value = std::string("b") }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"].mgl_filter; + mbgl::style::AllFilter expected = { + .filters = { + mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") }, + }, + }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@"b", @"z"]].mgl_filter; + mbgl::style::AllFilter expected = { + .filters = { + mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") }, + }, + }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].mgl_filter; + mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a IN %@", @[@"b", @"c"]].mgl_filter; + mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"'Mapbox' IN a"].mgl_filter, NSException, NSInvalidArgumentException); + + { + auto actual = [NSPredicate predicateWithFormat:@"{'b', 'c'} CONTAINS a"].mgl_filter; + mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@"b", @"c"]].mgl_filter; + mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a CONTAINS 'Mapbox'"].mgl_filter, NSException, NSInvalidArgumentException); + + { + auto actual = [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"].mgl_filter; + mbgl::style::AllFilter expected = { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"].mgl_filter; + mbgl::style::AnyFilter expected = { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' AND c == 'd')"].mgl_filter; + mbgl::style::NoneFilter expected = { + .filters = { + mbgl::style::AllFilter { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }, + }, + }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"].mgl_filter; + mbgl::style::NoneFilter expected = { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT a == nil"].mgl_filter; + mbgl::style::HasFilter expected = { .key = "a" }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT a != nil"].mgl_filter; + mbgl::style::NotHasFilter expected = { .key = "a" }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].mgl_filter; + mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT a IN %@", @[@"b", @"c"]].mgl_filter; + mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT {'b', 'c'} CONTAINS a"].mgl_filter; + mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + { + auto actual = [NSPredicate predicateWithFormat:@"NOT %@ CONTAINS a", @[@"b", @"c"]].mgl_filter; + mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } }; + MGLAssertEqualFilters(actual, expected); + } + + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BEGINSWITH 'L'"].mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a ENDSWITH 'itude'"].mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a LIKE 'glob?trotter'"].mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a MATCHES 'i\\w{18}n'"].mgl_filter, NSException, NSInvalidArgumentException); + NSPredicate *selectorPredicate = [NSPredicate predicateWithFormat:@"(SELF isKindOfClass: %@)", [MGLPolyline class]]; + XCTAssertThrowsSpecificNamed(selectorPredicate.mgl_filter, NSException, NSInvalidArgumentException); + + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary * _Nullable bindings) { + XCTAssertTrue(NO, @"Predicate block should not be evaluated."); + return NO; + }].mgl_filter, NSException, NSInvalidArgumentException); +} + +- (void)testPredication { + XCTAssertNil([NSPredicate mgl_predicateWithFilter:mbgl::style::NullFilter()]); + + { + mbgl::style::EqualsFilter filter = { .key = "a", .value = std::string("b") }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = 'b'"]); + } + + { + mbgl::style::NotHasFilter filter = { .key = "a" }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = nil"]); + } + + { + mbgl::style::NotEqualsFilter filter = { .key = "a", .value = std::string("b") }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != 'b'"]); + } + + { + mbgl::style::HasFilter filter = { .key = "a" }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != nil"]); + } + + { + mbgl::style::LessThanFilter filter = { .key = "a", .value = std::string("b") }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a < 'b'"]); + } + + { + mbgl::style::LessThanEqualsFilter filter = { .key = "a", .value = std::string("b") }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a <= 'b'"]); + } + + { + mbgl::style::GreaterThanFilter filter = { .key = "a", .value = std::string("b") }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a > 'b'"]); + } + + { + mbgl::style::GreaterThanEqualsFilter filter = { .key = "a", .value = std::string("b") }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a >= 'b'"]); + } + + { + mbgl::style::AllFilter filter = { + .filters = { + mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") }, + }, + }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]); + } + + { + mbgl::style::AllFilter filter = { + .filters = { + mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") }, + mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") }, + }, + }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]); + } + + { + mbgl::style::InFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].predicateFormat); + } + + { + mbgl::style::NotInFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].predicateFormat); + } + + { + mbgl::style::AllFilter filter; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]); + } + + { + mbgl::style::AllFilter filter = { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"]); + } + + { + mbgl::style::AnyFilter filter; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:NO]); + } + + { + mbgl::style::AnyFilter filter = { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"]); + } + + { + mbgl::style::NoneFilter filter; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]); + } + + { + mbgl::style::NoneFilter filter = { + .filters = { + mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") }, + mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") }, + }, + }; + XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"]); + } +} + +- (void)testSymmetry { + [self testSymmetryWithFormat:@"a = 1" reverseFormat:@"1 = a" mustRoundTrip:YES]; + [self testSymmetryWithFormat:@"a != 1" reverseFormat:@"1 != a" mustRoundTrip:YES]; + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = b"].mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 = 1"].mgl_filter, NSException, NSInvalidArgumentException); + + // In the predicate format language, $ is a special character denoting a + // variable. Use %K to escape the special feature attribute $id. + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"$id == 670861802"].mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = $id"].mgl_filter, NSException, NSInvalidArgumentException); + + [self testSymmetryWithFormat:@"a = nil" reverseFormat:@"nil = a" mustRoundTrip:YES]; + [self testSymmetryWithFormat:@"a != nil" reverseFormat:@"nil != a" mustRoundTrip:YES]; + + [self testSymmetryWithFormat:@"a < 1" reverseFormat:@"1 > a" mustRoundTrip:YES]; + [self testSymmetryWithFormat:@"a <= 1" reverseFormat:@"1 >= a" mustRoundTrip:YES]; + [self testSymmetryWithFormat:@"a > 1" reverseFormat:@"1 < a" mustRoundTrip:YES]; + [self testSymmetryWithFormat:@"a >= 1" reverseFormat:@"1 <= a" mustRoundTrip:YES]; + + [self testSymmetryWithFormat:@"a BETWEEN {1, 2}" reverseFormat:nil mustRoundTrip:YES]; + [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@1, @2]] + reversePredicate:nil + mustRoundTrip:YES]; + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"{1, 2} BETWEEN a"].mgl_filter, NSException, NSInvalidArgumentException); + NSPredicate *betweenSetPredicate = [NSPredicate predicateWithFormat:@"a BETWEEN %@", [NSSet setWithObjects:@1, @2, nil]]; + XCTAssertThrowsSpecificNamed(betweenSetPredicate.mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1}"].mgl_filter, NSException, NSInvalidArgumentException); + XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1, 2, 3}"].mgl_filter, NSException, NSInvalidArgumentException); + + [self testSymmetryWithFormat:@"a IN {1, 2}" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO]; + [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a IN %@", @[@1, @2]] + reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]] + mustRoundTrip:YES]; + + [self testSymmetryWithFormat:@"{1, 2} CONTAINS a" reverseFormat:@"a IN {1, 2}" mustRoundTrip:NO]; + [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]] + reversePredicate:[NSPredicate predicateWithFormat:@"a IN %@", @[@1, @2]] + mustRoundTrip:NO]; +} + +- (void)testSymmetryWithFormat:(NSString *)forwardFormat reverseFormat:(NSString *)reverseFormat mustRoundTrip:(BOOL)mustRoundTrip { + NSPredicate *forwardPredicate = [NSPredicate predicateWithFormat:forwardFormat]; + NSPredicate *reversePredicate = reverseFormat ? [NSPredicate predicateWithFormat:reverseFormat] : nil; + [self testSymmetryWithPredicate:forwardPredicate reversePredicate:reversePredicate mustRoundTrip:mustRoundTrip]; +} + +- (void)testSymmetryWithPredicate:(NSPredicate *)forwardPredicate reversePredicate:(NSPredicate *)reversePredicate mustRoundTrip:(BOOL)mustRoundTrip { + auto forwardFilter = forwardPredicate.mgl_filter; + NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter]; + if (mustRoundTrip) { + // Aggregates should round-trip, but for some reason only their format strings do. + XCTAssertEqualObjects(forwardPredicate.predicateFormat, forwardPredicateAfter.predicateFormat); + } + + if (reversePredicate) { + auto reverseFilter = reversePredicate.mgl_filter; + NSPredicate *reversePredicateAfter = [NSPredicate mgl_predicateWithFilter:reverseFilter]; + XCTAssertNotEqualObjects(reversePredicate, reversePredicateAfter); + + XCTAssertEqualObjects(forwardPredicateAfter, reversePredicateAfter); + } +} + +@end diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 139e2b014b..ebcf3a55cb 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -103,7 +103,7 @@ 35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */; }; 35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */; }; 35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */; }; - 35B8E08C1D6C8B5100E768D2 /* MGLFilterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */; }; + 35B8E08C1D6C8B5100E768D2 /* MGLPredicateTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B8E08B1D6C8B5100E768D2 /* MGLPredicateTests.mm */; }; 35CE61821D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35CE61801D4165D9004F2359 /* UIColor+MGLAdditions.h */; }; 35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35CE61801D4165D9004F2359 /* UIColor+MGLAdditions.h */; }; 35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35CE61811D4165D9004F2359 /* UIColor+MGLAdditions.mm */; }; @@ -570,7 +570,7 @@ 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationAnnotationView_Private.h; sourceTree = ""; }; 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLAdditions.h"; sourceTree = ""; }; 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSPredicate+MGLAdditions.mm"; sourceTree = ""; }; - 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFilterTests.mm; path = ../../darwin/test/MGLFilterTests.mm; sourceTree = ""; }; + 35B8E08B1D6C8B5100E768D2 /* MGLPredicateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLPredicateTests.mm; path = ../../darwin/test/MGLPredicateTests.mm; sourceTree = ""; }; 35CE61801D4165D9004F2359 /* UIColor+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MGLAdditions.h"; sourceTree = ""; }; 35CE61811D4165D9004F2359 /* UIColor+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIColor+MGLAdditions.mm"; sourceTree = ""; }; 35D13AB51D3D15E300AFB4E0 /* MGLStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayer.h; sourceTree = ""; }; @@ -937,11 +937,10 @@ isa = PBXGroup; children = ( 3575798F1D513EF1000B822E /* Layers */, - 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */, + 40CFA64E1D78754A008103BD /* Sources */, 357F09091DF84F3800941873 /* MGLStyleValueTests.h */, 3599A3E51DF708BC00E77FB2 /* MGLStyleValueTests.m */, DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */, - 40CFA64E1D78754A008103BD /* Sources */, ); name = Styling; sourceTree = ""; @@ -1094,9 +1093,11 @@ DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */, 353D23951D0B0DFE002BE09D /* MGLAnnotationViewTests.m */, DA35A2C31CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m */, + 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */, DA35A2C41CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m */, DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */, 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */, + DD58A4C51D822BD000E1F038 /* MGLExpressionTests.mm */, DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */, DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */, DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */, @@ -1105,9 +1106,8 @@ DA2E885D1CC0382C00F24E7B /* MGLOfflinePackTests.m */, DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */, DA2E885F1CC0382C00F24E7B /* MGLOfflineStorageTests.m */, - 35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */, + 35B8E08B1D6C8B5100E768D2 /* MGLPredicateTests.mm */, DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */, - DD58A4C51D822BD000E1F038 /* MGLExpressionTests.mm */, DA2E88551CC036F400F24E7B /* Info.plist */, DA2784FB1DF02FF4001D5B8D /* Media.xcassets */, ); @@ -1785,6 +1785,7 @@ TargetAttributes = { DA1DC9491CB6C1C2006E619F = { CreatedOnToolsVersion = 7.3; + DevelopmentTeam = GJZR2MEM28; LastSwiftMigration = 0820; }; DA25D5B81CCD9EDE00607828 = { @@ -2002,7 +2003,7 @@ DA2207BF1DC0805F0002F84D /* MGLStyleValueTests.swift in Sources */, 40CFA6511D7875BB008103BD /* MGLShapeSourceTests.mm in Sources */, DA35A2C51CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m in Sources */, - 35B8E08C1D6C8B5100E768D2 /* MGLFilterTests.mm in Sources */, + 35B8E08C1D6C8B5100E768D2 /* MGLPredicateTests.mm in Sources */, DD58A4C61D822BD000E1F038 /* MGLExpressionTests.mm in Sources */, 3575798B1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m in Sources */, DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */, diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 951ae1bd37..56872a1b19 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -99,7 +99,7 @@ DA87A9981DC9D88400810D09 /* MGLShapeSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9961DC9D88400810D09 /* MGLShapeSourceTests.mm */; }; DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */; }; DA87A99C1DC9D8DD00810D09 /* MGLShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99B1DC9D8DD00810D09 /* MGLShapeSource_Private.h */; }; - DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */; }; + DA87A99E1DC9DC2100810D09 /* MGLPredicateTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D84B1D6DD75B00E95907 /* MGLPredicateTests.mm */; }; DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */; }; DA87A9A11DC9DCB400810D09 /* MGLRuntimeStylingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F257B1D51C5F40010E6B5 /* MGLRuntimeStylingHelper.m */; }; DA87A9A21DC9DCF100810D09 /* MGLFillStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25741D51C5F40010E6B5 /* MGLFillStyleLayerTests.m */; }; @@ -287,7 +287,7 @@ 35C5D8441D6DD66D00E95907 /* NSComparisonPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSComparisonPredicate+MGLAdditions.mm"; sourceTree = ""; }; 35C5D8451D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCompoundPredicate+MGLAdditions.h"; sourceTree = ""; }; 35C5D8461D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSCompoundPredicate+MGLAdditions.mm"; sourceTree = ""; }; - 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFilterTests.mm; sourceTree = ""; }; + 35C5D84B1D6DD75B00E95907 /* MGLPredicateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLPredicateTests.mm; path = ../../darwin/test/MGLPredicateTests.mm; sourceTree = ""; }; 35D65C581D65AD5500722C23 /* NSDate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+MGLAdditions.h"; sourceTree = ""; }; 35D65C591D65AD5500722C23 /* NSDate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDate+MGLAdditions.mm"; sourceTree = ""; }; 4032C5B91DE1EEBA0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleEnumAttributeAdditions.h"; sourceTree = ""; }; @@ -714,7 +714,6 @@ children = ( DA8F257C1D51C5F40010E6B5 /* Layers */, DA87A99A1DC9D88800810D09 /* Sources */, - 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */, 353722EB1DF850ED004D2F3F /* MGLStyleValueTests.h */, 3599A3E71DF70E2000E77FB2 /* MGLStyleValueTests.m */, DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */, @@ -883,17 +882,18 @@ DA8F257D1D51C5F40010E6B5 /* Styling */, DAEDC4311D6033F1000224FF /* MGLAttributionInfoTests.m */, DAEDC4361D606291000224FF /* MGLAttributionButtonTests.m */, - 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */, DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */, + 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */, DA35A2B51CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m */, DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */, + DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */, DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */, DAE6C3C81CC34BD800DB3429 /* MGLGeometryTests.mm */, DAE6C3C91CC34BD800DB3429 /* MGLOfflinePackTests.m */, DAE6C3CA1CC34BD800DB3429 /* MGLOfflineRegionTests.m */, DAE6C3CB1CC34BD800DB3429 /* MGLOfflineStorageTests.m */, + 35C5D84B1D6DD75B00E95907 /* MGLPredicateTests.mm */, DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */, - DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */, DAE6C33A1CC30DB200DB3429 /* Info.plist */, DA2784FD1DF03060001D5B8D /* Media.xcassets */, ); @@ -1323,7 +1323,7 @@ DAE6C3D51CC34C9900DB3429 /* MGLOfflineStorageTests.m in Sources */, 40E1601D1DF217D6005EA6D9 /* MGLStyleLayerTests.m in Sources */, DA87A9A61DCACC5000810D09 /* MGLCircleStyleLayerTests.m in Sources */, - DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */, + DA87A99E1DC9DC2100810D09 /* MGLPredicateTests.mm in Sources */, DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */, DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.m in Sources */, DAE6C3D31CC34C9900DB3429 /* MGLOfflinePackTests.m in Sources */, -- cgit v1.2.1 From aef36956ee062ea2992c43d658cebf52954b5213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 26 Dec 2016 15:07:43 -0800 Subject: [ios, macos] Cleaned up expression conversion --- platform/darwin/src/NSArray+MGLAdditions.mm | 4 +- .../src/NSComparisonPredicate+MGLAdditions.mm | 10 ++-- platform/darwin/src/NSDictionary+MGLAdditions.mm | 2 +- platform/darwin/src/NSExpression+MGLAdditions.h | 10 ++-- platform/darwin/src/NSExpression+MGLAdditions.mm | 60 +++++++++------------- platform/darwin/src/NSPredicate+MGLAdditions.mm | 34 ++++++------ platform/darwin/test/MGLExpressionTests.mm | 54 ++++++++++--------- platform/darwin/test/MGLPredicateTests.mm | 13 +++-- 8 files changed, 95 insertions(+), 92 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/NSArray+MGLAdditions.mm b/platform/darwin/src/NSArray+MGLAdditions.mm index f2c5a096cc..8ec344f580 100644 --- a/platform/darwin/src/NSArray+MGLAdditions.mm +++ b/platform/darwin/src/NSArray+MGLAdditions.mm @@ -17,9 +17,9 @@ vector.push_back(propertyMap); } else { NSExpression *expression = [NSExpression expressionForConstantValue:value]; - vector.push_back([expression mgl_filterValue]); + vector.push_back(expression.mgl_constantMBGLValue); } - } + } return vector; } diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm index 58390b0b81..58b37fae0e 100644 --- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm @@ -105,7 +105,7 @@ } mbgl::style::InFilter inFilter; inFilter.key = leftExpression.keyPath.UTF8String; - inFilter.values = rightExpression.mgl_filterValues; + inFilter.values = rightExpression.mgl_aggregateMBGLValue; return inFilter; } case NSContainsPredicateOperatorType: { @@ -119,7 +119,7 @@ } mbgl::style::InFilter inFilter; inFilter.key = rightExpression.keyPath.UTF8String; - inFilter.values = leftExpression.mgl_filterValues; + inFilter.values = leftExpression.mgl_aggregateMBGLValue; return inFilter; } case NSBetweenPredicateOperatorType: { @@ -131,7 +131,7 @@ [NSException raise:NSInvalidArgumentException format:@"Right side of BETWEEN predicate must be an array."]; // not NSSet } - auto values = rightExpression.mgl_filterValues; + auto values = rightExpression.mgl_aggregateMBGLValue; if (values.size() != 2) { [NSException raise:NSInvalidArgumentException format:@"Right side of BETWEEN predicate must have two items."]; @@ -182,9 +182,9 @@ NSExpressionType rightType = rightExpression.expressionType; mbgl::Value value; if (leftType == NSKeyPathExpressionType && rightType == NSConstantValueExpressionType) { - value = rightExpression.mgl_filterValue; + value = rightExpression.mgl_constantMBGLValue; } else if (leftType == NSConstantValueExpressionType && rightType == NSKeyPathExpressionType) { - value = leftExpression.mgl_filterValue; + value = leftExpression.mgl_constantMBGLValue; } else { [NSException raise:NSInvalidArgumentException format:@"Comparison predicate must compare an attribute (as a key path) to a constant or vice versa."]; diff --git a/platform/darwin/src/NSDictionary+MGLAdditions.mm b/platform/darwin/src/NSDictionary+MGLAdditions.mm index 1023e91a48..aad7fd8810 100644 --- a/platform/darwin/src/NSDictionary+MGLAdditions.mm +++ b/platform/darwin/src/NSDictionary+MGLAdditions.mm @@ -15,7 +15,7 @@ propertyMap[[key UTF8String]] = [array mgl_vector]; } else { NSExpression *expression = [NSExpression expressionForConstantValue:self[key]]; - propertyMap[[key UTF8String]] = [expression mgl_filterValue]; + propertyMap[[key UTF8String]] = expression.mgl_constantMBGLValue; } } return propertyMap; diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h index 6d0fff5760..c60d6d78ba 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.h +++ b/platform/darwin/src/NSExpression+MGLAdditions.h @@ -2,10 +2,14 @@ #include +NS_ASSUME_NONNULL_BEGIN + @interface NSExpression (MGLAdditions) -- (mbgl::Value)mgl_filterValue; -- (std::vector)mgl_filterValues; -- (mbgl::FeatureIdentifier)mgl_featureIdentifier; +@property (nonatomic, readonly) mbgl::Value mgl_constantMBGLValue; +@property (nonatomic, readonly) std::vector mgl_aggregateMBGLValue; +@property (nonatomic, readonly) mbgl::FeatureIdentifier mgl_featureIdentifier; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 97f3e11dba..f11a1919cf 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -2,31 +2,25 @@ @implementation NSExpression (MGLAdditions) -- (std::vector)mgl_filterValues -{ +- (std::vector)mgl_aggregateMBGLValue { if ([self.constantValue isKindOfClass:[NSArray class]] || [self.constantValue isKindOfClass:[NSSet class]]) { std::vector convertedValues; - for (id item in self.constantValue) { - id constantValue = item; - if ([item isKindOfClass:[NSExpression class]]) { - constantValue = [constantValue constantValue]; + for (id value in self.constantValue) { + NSExpression *expression = value; + if (![expression isKindOfClass:[NSExpression class]]) { + expression = [NSExpression expressionForConstantValue:expression]; } - convertedValues.push_back([self mgl_convertedValueWithValue:constantValue]); + convertedValues.push_back(expression.mgl_constantMBGLValue); } return convertedValues; } [NSException raise:NSInvalidArgumentException format:@"Constant value expression must contain an array or set."]; - return { }; -} - -- (mbgl::Value)mgl_filterValue -{ - return [self mgl_convertedValueWithValue:self.constantValue]; + return {}; } -- (mbgl::Value)mgl_convertedValueWithValue:(id)value -{ +- (mbgl::Value)mgl_constantMBGLValue { + id value = self.constantValue; if ([value isKindOfClass:NSString.class]) { return { std::string([(NSString *)value UTF8String]) }; } else if ([value isKindOfClass:NSNumber.class]) { @@ -66,30 +60,26 @@ [NSException raise:NSInvalidArgumentException format:@"Can’t convert %s:%@ to mbgl::Value", [value objCType], value]; } - return { }; + return {}; } -- (mbgl::FeatureIdentifier)mgl_featureIdentifier -{ - id value = self.constantValue; - mbgl::Value mbglValue = [self mgl_filterValue]; +- (mbgl::FeatureIdentifier)mgl_featureIdentifier { + mbgl::Value mbglValue = self.mgl_constantMBGLValue; - if ([value isKindOfClass:NSString.class]) { + if (mbglValue.is()) { return mbglValue.get(); - } else if ([value isKindOfClass:NSNumber.class]) { - NSNumber *number = (NSNumber *)value; - if ((strcmp([number objCType], @encode(char)) == 0) || - (strcmp([number objCType], @encode(BOOL)) == 0)) { - return mbglValue.get(); - } else if ( strcmp([number objCType], @encode(double)) == 0 || - strcmp([number objCType], @encode(float)) == 0) { - return mbglValue.get(); - } else if ([number compare:@(0)] == NSOrderedDescending || - [number compare:@(0)] == NSOrderedSame) { - return mbglValue.get(); - } else if ([number compare:@(0)] == NSOrderedAscending) { - return mbglValue.get(); - } + } + if (mbglValue.is()) { + return mbglValue.get(); + } + if (mbglValue.is()) { + return mbglValue.get(); + } + if (mbglValue.is()) { + return mbglValue.get(); + } + if (mbglValue.is()) { + return mbglValue.get(); } return {}; diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index f999df96b0..0ac68095f9 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -5,7 +5,7 @@ class FilterEvaluator { public: - NSArray* getPredicates(std::vector filters) { + NSArray *getPredicates(std::vector filters) { NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:filters.size()]; for (auto filter : filters) { [predicates addObject:mbgl::style::Filter::visit(filter, FilterEvaluator())]; @@ -13,52 +13,52 @@ public: return predicates; } - NSArray* getValues(std::vector values) { + NSExpression *getValues(std::vector values) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()]; for (auto value : values) { id constantValue = mbgl::Value::visit(value, ValueEvaluator()); [array addObject:[NSExpression expressionForConstantValue:constantValue]]; } - return array; + return [NSExpression expressionForAggregate:array]; } - NSPredicate* operator()(mbgl::style::NullFilter filter) { + NSPredicate *operator()(mbgl::style::NullFilter filter) { return nil; } - NSPredicate* operator()(mbgl::style::EqualsFilter filter) { + NSPredicate *operator()(mbgl::style::EqualsFilter filter) { return [NSPredicate predicateWithFormat:@"%K == %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; } - NSPredicate* operator()(mbgl::style::NotEqualsFilter filter) { + NSPredicate *operator()(mbgl::style::NotEqualsFilter filter) { return [NSPredicate predicateWithFormat:@"%K != %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; } - NSPredicate* operator()(mbgl::style::GreaterThanFilter filter) { + NSPredicate *operator()(mbgl::style::GreaterThanFilter filter) { return [NSPredicate predicateWithFormat:@"%K > %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; } - NSPredicate* operator()(mbgl::style::GreaterThanEqualsFilter filter) { + NSPredicate *operator()(mbgl::style::GreaterThanEqualsFilter filter) { return [NSPredicate predicateWithFormat:@"%K >= %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; } - NSPredicate* operator()(mbgl::style::LessThanFilter filter) { + NSPredicate *operator()(mbgl::style::LessThanFilter filter) { return [NSPredicate predicateWithFormat:@"%K < %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; } - NSPredicate* operator()(mbgl::style::LessThanEqualsFilter filter) { + NSPredicate *operator()(mbgl::style::LessThanEqualsFilter filter) { return [NSPredicate predicateWithFormat:@"%K <= %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; } - NSPredicate* operator()(mbgl::style::InFilter filter) { + NSPredicate *operator()(mbgl::style::InFilter filter) { return [NSPredicate predicateWithFormat:@"%K IN %@", @(filter.key.c_str()), getValues(filter.values)]; } - NSPredicate* operator()(mbgl::style::NotInFilter filter) { + NSPredicate *operator()(mbgl::style::NotInFilter filter) { return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @(filter.key.c_str()), getValues(filter.values)]; } - NSPredicate* operator()(mbgl::style::AnyFilter filter) { + NSPredicate *operator()(mbgl::style::AnyFilter filter) { NSArray *subpredicates = getPredicates(filter.filters); if (subpredicates.count) { return [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates]; @@ -66,7 +66,7 @@ public: return [NSPredicate predicateWithValue:NO]; } - NSPredicate* operator()(mbgl::style::AllFilter filter) { + NSPredicate *operator()(mbgl::style::AllFilter filter) { // Convert [all, [>=, key, lower], [<=, key, upper]] to key BETWEEN {lower, upper} if (filter.filters.size() == 2) { auto leftFilter = filter.filters[0]; @@ -108,7 +108,7 @@ public: return [NSPredicate predicateWithValue:YES]; } - NSPredicate* operator()(mbgl::style::NoneFilter filter) { + NSPredicate *operator()(mbgl::style::NoneFilter filter) { NSArray *subpredicates = getPredicates(filter.filters); if (subpredicates.count > 1) { NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates]; @@ -120,11 +120,11 @@ public: } } - NSPredicate* operator()(mbgl::style::HasFilter filter) { + NSPredicate *operator()(mbgl::style::HasFilter filter) { return [NSPredicate predicateWithFormat:@"%K != nil", @(filter.key.c_str())]; } - NSPredicate* operator()(mbgl::style::NotHasFilter filter) { + NSPredicate *operator()(mbgl::style::NotHasFilter filter) { return [NSPredicate predicateWithFormat:@"%K == nil", @(filter.key.c_str())]; } diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index e78f87a99b..00b57c15f0 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -28,27 +28,35 @@ - (void)testExpressionConversionString { NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@"bar"]; - mbgl::Value convertedValue = predicate.rightExpression.mgl_filterValue; - XCTAssert(convertedValue.is() == true); + mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue; + XCTAssertTrue(convertedValue.is()); XCTAssertEqualObjects(@(convertedValue.get().c_str()), @"bar"); } +- (void)testExpressionConversionStringWithUnicode +{ + NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@"🆔🆗🇦🇶"]; + mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue; + XCTAssertTrue(convertedValue.is()); + XCTAssertEqual(convertedValue.get(), "🆔🆗🇦🇶"); +} + #pragma mark - Boolean Tests - (void)testExpressionConversionBooleanTrue { NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@YES]; - mbgl::Value convertedValue = predicate.rightExpression.mgl_filterValue; - XCTAssert(convertedValue.is() == true); - XCTAssert(convertedValue.get() == true); + mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue; + XCTAssertTrue(convertedValue.is()); + XCTAssertEqual(convertedValue.get(), true); } - (void)testExpressionConversionBooleanFalse { NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:@NO]; - mbgl::Value convertedValue = predicate.rightExpression.mgl_filterValue; - XCTAssert(convertedValue.is() == true); - XCTAssert(convertedValue.get() == false); + mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue; + XCTAssertTrue(convertedValue.is()); + XCTAssertEqual(convertedValue.get(), false); } #pragma mark - Floating Point Tests @@ -59,12 +67,12 @@ mbgl::Value convertedValue; predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithDouble:DBL_MIN]]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), DBL_MIN); predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithDouble:DBL_MAX]]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), DBL_MAX); } @@ -72,7 +80,7 @@ - (void)testExpressionConversionFloat { // Because we can't guarantee precision when using float, and because - // we warn the user to this effect in mgl_convertedValueWithValue:, + // we warn the user to this effect in -[NSExpression mgl_constantMBGLValue], // we just check that things are in the ballpark here with integer values // and some lower-precision checks. @@ -80,26 +88,24 @@ mbgl::Value convertedValue; predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:-1]]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), -1); predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:1]]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), 1); predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:-23.232342]]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); - XCTAssertLessThan(-23.24, convertedValue.get()); - XCTAssertGreaterThan(-23.23, convertedValue.get()); + XCTAssertEqualWithAccuracy(convertedValue.get(), -23.232342, 0.000001); predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNumber numberWithFloat:23.232342]]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); - XCTAssertLessThan(23.23, convertedValue.get()); - XCTAssertGreaterThan(23.24, convertedValue.get()); + XCTAssertEqualWithAccuracy(convertedValue.get(), 23.232342, 0.000001); } #pragma mark - Integer Tests @@ -132,7 +138,7 @@ for (NSNumber *min in minValues) { predicate = [self equalityComparisonPredicateWithRightConstantValue:min]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), min.longLongValue); } @@ -144,7 +150,7 @@ for (NSNumber *max in maxValues) { predicate = [self equalityComparisonPredicateWithRightConstantValue:max]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), max.unsignedLongLongValue); } @@ -179,7 +185,7 @@ for (NSNumber *min in minValues) { predicate = [self equalityComparisonPredicateWithRightConstantValue:min]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), min.unsignedLongLongValue); } @@ -191,7 +197,7 @@ for (NSNumber *max in maxValues) { predicate = [self equalityComparisonPredicateWithRightConstantValue:max]; - convertedValue = predicate.rightExpression.mgl_filterValue; + convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); XCTAssertEqual(convertedValue.get(), max.unsignedLongLongValue); } @@ -202,7 +208,7 @@ - (void)testExpressionConversionNull { NSComparisonPredicate *predicate = [self equalityComparisonPredicateWithRightConstantValue:[NSNull null]]; - mbgl::Value convertedValue = predicate.rightExpression.mgl_filterValue; + mbgl::Value convertedValue = predicate.rightExpression.mgl_constantMBGLValue; XCTAssertTrue(convertedValue.is()); } diff --git a/platform/darwin/test/MGLPredicateTests.mm b/platform/darwin/test/MGLPredicateTests.mm index 07466dfd13..fbd144d28a 100644 --- a/platform/darwin/test/MGLPredicateTests.mm +++ b/platform/darwin/test/MGLPredicateTests.mm @@ -369,9 +369,9 @@ namespace mbgl { [self testSymmetryWithFormat:@"a > 1" reverseFormat:@"1 < a" mustRoundTrip:YES]; [self testSymmetryWithFormat:@"a >= 1" reverseFormat:@"1 <= a" mustRoundTrip:YES]; - [self testSymmetryWithFormat:@"a BETWEEN {1, 2}" reverseFormat:nil mustRoundTrip:YES]; + [self testSymmetryWithFormat:@"a BETWEEN {1, 2}" reverseFormat:@"1 <= a && 2 >= a" mustRoundTrip:YES]; [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@1, @2]] - reversePredicate:nil + reversePredicate:[NSPredicate predicateWithFormat:@"1 <= a && 2 >= a"] mustRoundTrip:YES]; XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"{1, 2} BETWEEN a"].mgl_filter, NSException, NSInvalidArgumentException); NSPredicate *betweenSetPredicate = [NSPredicate predicateWithFormat:@"a BETWEEN %@", [NSSet setWithObjects:@1, @2, nil]]; @@ -384,9 +384,11 @@ namespace mbgl { reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]] mustRoundTrip:YES]; - [self testSymmetryWithFormat:@"{1, 2} CONTAINS a" reverseFormat:@"a IN {1, 2}" mustRoundTrip:NO]; + // The reverse formats here are a bit backwards because we canonicalize + // a reverse CONTAINS to a forward IN. + [self testSymmetryWithFormat:@"{1, 2} CONTAINS a" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO]; [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]] - reversePredicate:[NSPredicate predicateWithFormat:@"a IN %@", @[@1, @2]] + reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]] mustRoundTrip:NO]; } @@ -400,7 +402,8 @@ namespace mbgl { auto forwardFilter = forwardPredicate.mgl_filter; NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter]; if (mustRoundTrip) { - // Aggregates should round-trip, but for some reason only their format strings do. + // A collection of ints may turn into an aggregate of longs, for + // example, so compare formats instead of the predicates themselves. XCTAssertEqualObjects(forwardPredicate.predicateFormat, forwardPredicateAfter.predicateFormat); } -- cgit v1.2.1 From 63b1d652f826d786e7502beb0e2abb6d78e508d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Mon, 26 Dec 2016 15:09:01 -0800 Subject: [ios, macos] Note that no modifier operators are supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There’s also an “l” operator for locale sensitivity. --- platform/darwin/src/MGLVectorStyleLayer.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h index ff07a71a76..50e56d8643 100644 --- a/platform/darwin/src/MGLVectorStyleLayer.h +++ b/platform/darwin/src/MGLVectorStyleLayer.h @@ -62,8 +62,9 @@ NS_ASSUME_NONNULL_BEGIN To test whether a feature has or lacks a specific attribute, compare the attribute to `NULL` or `NIL`. Predicates created using the `+[NSPredicate predicateWithValue:]` method are also supported. String operators and custom operators are not supported. For details about the predicate format string syntax, consult the “Predicate - Format String Syntax” chapter of the “Predicate Programming Guide” in Apple - developer documentation. + Format String Syntax” chapter of the + “Predicate Programming Guide” + in Apple developer documentation. The predicate's left-hand expression must be a string that identifies a feature attribute or, alternatively, one of the following special attributes: @@ -119,9 +120,10 @@ NS_ASSUME_NONNULL_BEGIN Automatic type casting is not performed. Therefore, a feature only matches this predicate if its value for the attribute in question is of the same type as the - value specified in the predicate. Also, operator modifiers `c`, `d`, and the - combined `cd` for case and diacritic insensitivity are unsupported for - comparison and aggregate operators that are used in the predicate. + value specified in the predicate. Also, operator modifiers such as `c` (for + case insensitivity), `d` (for diacritic insensitivity), and `l` (for locale + sensitivity) are unsupported for comparison and aggregate operators that are + used in the predicate. It is possible to create expressions that contain special characters in the predicate format syntax. This includes the `$` in the `$id` and `$type` special -- cgit v1.2.1 From 50ae3eb3c0985567a0f86d08337d7cb8bed79a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 4 Jan 2017 12:19:31 -0800 Subject: [ios, macos] Insert example code in original headers (#7569) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [ios, macos] Removed extraneous code fences * [ios] Streamlined example delimiters Use test method names as names of example blocks and test method documentation comments as front matter for examples. Set off example blocks using a syntax similar to playground markup syntax. Avoid hard-coding indentation levels. Trigger Xcode build error when an error occurs in the script. * [ios] Removed platform-specific code from examples * [ios] Fixed logic error The comment said 200 while the code said 1,500. * [ios] Formalize build phase input * [ios] Insert examples into original source documentation Rewrote the example code insertion script to work on the original source files and overwrite any existing code examples on the same symbols. The script uses SourceKitten to find the documentation comment for the symbol named by the test method. Replaced the Run Script build phase that runs the example code insertion script with a make rule that runs the same script. Inlined skeleton examples minus the contents of the code blocks. * [ios] Fixed syntax error * [ios] Ran ios-add-examples-to-docs * [ios] Avoid touching unchanged headers * [ios] Refactored example insertion script * [ios] Point jazzy at original sources * [ios] Invoke SourceKitten only once * [ios] Look for methods as well as properties * [ios] Thoroughly search for code blocks in doc comments Refactored the example code insertion script to index test methods by their names, then recursively search the SourceKitten output for documentation comments that contain Swift code blocks, replacing each code block with the associated test method body. * [ios, macos] Enabled example insertion for macOS The example code insertion script is now platform-agnostic. * [ios, macos] Fixed documentation example tests Set the map view’s style to a minimal local JSON file. Wait for the style to finish loading before running each test. Corrected CGVector type. * [ios, macos] Dry run mode The output of this mode isn’t a good indicator of whether any files would’ve needed to be changed, because the presence of a conditional compilation block in one of the test methods means this script would always change and revert the corresponding comment. * [ios] Fixed test failure The iOS implementation of MGLMapView tries to show the Streets style by default even if no access token has been set. Avoid a race condition and frequent test failure by specifying the minimal style on initialization. * [ios, macos] Ensure SourceKitten is installed before inserting example code * [ios, macos] Tear down map view after each test Keep map views from previous tests from hanging around, potentially obscuring the result of a subsequent test. Set the access token to a bogus token upfront for all style layer tests. Unified MGLStyle usage within MGLStyleTests. * [ios, macos] Reinsert examples after generating runtime styling headers --- platform/darwin/scripts/update-examples.js | 152 +++++++++++++++ platform/darwin/src/MGLCircleStyleLayer.h | 17 +- platform/darwin/src/MGLFillStyleLayer.h | 12 +- platform/darwin/src/MGLLineStyleLayer.h | 17 +- platform/darwin/src/MGLRasterSource.h | 15 +- platform/darwin/src/MGLRasterStyleLayer.h | 10 +- platform/darwin/src/MGLShapeSource.h | 14 +- platform/darwin/src/MGLStyleLayer.h.ejs | 7 +- platform/darwin/src/MGLSymbolStyleLayer.h | 17 +- platform/darwin/src/MGLVectorSource.h | 15 +- platform/darwin/src/MGLVectorStyleLayer.h | 20 +- .../darwin/test/MGLDocumentationExampleTests.swift | 209 +++++++++++++++++++++ platform/darwin/test/MGLStyleLayerTests.m | 8 +- platform/darwin/test/MGLStyleTests.mm | 49 +++-- platform/darwin/test/one-liner.json | 1 + platform/ios/DEVELOPING.md | 16 ++ platform/ios/ios.xcodeproj/project.pbxproj | 39 +--- platform/ios/jazzy.yml | 2 + platform/ios/scripts/add-examples-to-docs.js | 65 ------- platform/ios/scripts/document.sh | 5 - .../ios/test/MGLDocumentationExampleTests.swift | 204 -------------------- platform/macos/DEVELOPING.md | 26 +++ platform/macos/macos.xcodeproj/project.pbxproj | 8 + 23 files changed, 578 insertions(+), 350 deletions(-) create mode 100644 platform/darwin/scripts/update-examples.js create mode 100644 platform/darwin/test/MGLDocumentationExampleTests.swift create mode 100644 platform/darwin/test/one-liner.json delete mode 100644 platform/ios/scripts/add-examples-to-docs.js delete mode 100644 platform/ios/test/MGLDocumentationExampleTests.swift (limited to 'platform') diff --git a/platform/darwin/scripts/update-examples.js b/platform/darwin/scripts/update-examples.js new file mode 100644 index 0000000000..2aeb80e139 --- /dev/null +++ b/platform/darwin/scripts/update-examples.js @@ -0,0 +1,152 @@ +'use strict'; + +const fs = require('fs'); +const execFileSync = require('child_process').execFileSync; +const _ = require('lodash'); + +const examplesSrc = fs.readFileSync('platform/darwin/test/MGLDocumentationExampleTests.swift', 'utf8'); + +// Regex extracts the following block +// /** Front matter to describe the example. **/ +// func testMGLClass$member() { +// ... +// //#-example-code +// let sampleCode: String? +// //#-end-example-code +// ... +// } +// +// into the following regex groups: +// 1 (test method name): "MGLClass" or "MGLClass$member" or "MGLClass$initWithArg_anotherArg_" +// 2 (indentation): " " +// 3 (sample code): "let sampleCode: String?" +const exampleRegex = /func test([\w$]+)\s*\(\)\s*\{[^]*?\n([ \t]+)\/\/#-example-code\n([^]+?)\n\2\/\/#-end-example-code\n/gm; + +/** + * Returns the given source with example code inserted into the documentation + * comment for the symbol at the given one-based line. + * + * @param {String} src Source code to insert the example code into. + * @param {Number} line One-based line number of the symbol being documented. + * @param {String} exampleCode Example code to insert. + * @returns {String} `src` with `exampleCode` inserted just above `line`. + */ +function completeSymbolInSource(src, line, exampleCode) { + // Split the file contents right before the symbol declaration (but after its documentation comment). + let srcUpToSymbol = src.split('\n', line - 1).join('\n'); + let srcFromSymbol = src.substr(srcUpToSymbol.length); + + // Match the documentation comment block that is not followed by the beginning or end of a declaration. + let commentMatch = srcUpToSymbol.match(/\/\*\*\s*(?:[^*]|\*(?!\/))+?\s*\*\/[^;{}]*?$/); + + // Replace the Swift code block with the test method’s contents. + let completedComment = commentMatch[0].replace(/^([ \t]*)```swift\n[^]*?```/m, function (m, indentation) { + // Apply the original indentation to each line. + return ('```swift\n' + exampleCode + '\n```').replace(/^/gm, indentation); + }); + + // Splice the modified comment into the overall file contents. + srcUpToSymbol = (srcUpToSymbol.substr(0, commentMatch.index) + completedComment + + srcUpToSymbol.substr(commentMatch.index + commentMatch[0].length)); + return srcUpToSymbol + srcFromSymbol; +} + +let examples = {}; +let match; +while ((match = exampleRegex.exec(examplesSrc)) !== null) { + let testMethodName = match[1], + indentation = match[2], + exampleCode = match[3]; + + // Trim leading whitespace from the example code. + exampleCode = exampleCode.replace(new RegExp('^' + indentation, 'gm'), ''); + + examples[testMethodName] = exampleCode; +} + +function completeExamples(os) { + console.log(`Installing ${os} SDK examples…`); + + let sdk = os === 'iOS' ? 'iphonesimulator' : 'macosx'; + let sysroot = execFileSync('xcrun', ['--show-sdk-path', '--sdk', sdk]).toString().trim(); + let umbrellaPath = `platform/${os.toLowerCase()}/src/Mapbox.h`; + let docArgs = ['doc', '--objc', umbrellaPath, '--', + '-x', 'objective-c', '-I', 'platform/darwin/src/', '-isysroot', sysroot]; + let docStr = execFileSync('sourcekitten', docArgs).toString().trim(); + let docJson = JSON.parse(docStr); + _.forEach(docJson, function (result) { + _.forEach(result, function (structure, path) { + let src; + let newSrc; + // Recursively search for code blocks in documentation comments and populate + // them with example code from the test methods. Find and replace the code + // blocks in reverse to keep the SourceKitten line numbers accurate. + _.forEachRight(structure['key.substructure'], function completeSubstructure(substructure, idx, substructures, symbolPath) { + if (!symbolPath) { + symbolPath = [substructure['key.name']]; + } + _.forEachRight(substructure['key.substructure'], function (substructure, idx, substructures) { + completeSubstructure(substructure, idx, substructures, _.concat(symbolPath, substructure['key.name'])); + }); + + let comment = substructure['key.doc.comment']; + if (!comment || !comment.match(/^(?:\s*)```swift\n/m)) { + return; + } + + // Lazily read in the existing file. + if (!src) { + newSrc = src = fs.readFileSync(path, 'utf8'); + } + + // Get the contents of the test method whose name matches the symbol path. + let testMethodName = symbolPath.join('$').replace(/$[+-]/, '').replace(/:/g, '_'); + let example = examples[testMethodName]; + if (!example) { + console.error(`MGLDocumentationExampleTests.${testMethodName}() not found.`); + process.exit(1); + } + + // Resolve conditional compilation blocks. + example = example.replace(/^(\s*)#if\s+os\((iOS|macOS)\)\n([^]*?)(?:^\1#else\n([^]*?))?^\1#endif\n/gm, + function (m, indentation, ifOs, ifCase, elseCase) { + return (os === ifOs ? ifCase : elseCase).replace(new RegExp('^ ', 'gm'), ''); + }); + + // Insert the test method contents into the documentation comment just + // above the substructure. + let startLine = substructure['key.parsed_scope.start']; + newSrc = completeSymbolInSource(newSrc, startLine, example); + }); + + if (!src) { + return; + } + + // Write out the modified file contents. + if (src === newSrc) { + console.log('Skipping', path); + } else { + console.log('Updating', path); + if (['0', 'false'].indexOf(process.env.DRY_RUN || '0') !== -1) { + fs.writeFileSync(path, newSrc); + } + } + }); + }); +} + +function ensureSourceKittenIsInstalled() { + try { + execFileSync('which', ['sourcekitten']); + } catch (e) { + console.log(`Installing SourceKitten via Homebrew…`); + execFileSync('brew', ['install', 'sourcekitten']); + } +} + +ensureSourceKittenIsInstalled(); + +// Where a particular comment is part of both SDKs, prefer the iOS example. +completeExamples('macOS'); +completeExamples('iOS'); diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h index b57e245da2..d2e043e22a 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.h +++ b/platform/darwin/src/MGLCircleStyleLayer.h @@ -59,8 +59,21 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) { otherwise, find it using the `MGLStyle.layers` property. You can also create a new circle style layer and add it to the style using a method such as `-[MGLStyle addLayer:]`. - - + + ### Example + + ```swift + let layer = MGLCircleStyleLayer(identifier: "circles", source: population) + layer.sourceLayerIdentifier = "population" + layer.circleColor = MGLStyleValue(rawValue: .green) + layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [ + 12: MGLStyleValue(rawValue: 2), + 22: MGLStyleValue(rawValue: 180) + ]) + layer.circleOpacity = MGLStyleValue(rawValue: 0.7) + layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married") + mapView.style.addLayer(layer) + ``` */ @interface MGLCircleStyleLayer : MGLVectorStyleLayer diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h index 2638e85aa5..184f44ef65 100644 --- a/platform/darwin/src/MGLFillStyleLayer.h +++ b/platform/darwin/src/MGLFillStyleLayer.h @@ -37,8 +37,16 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) { otherwise, find it using the `MGLStyle.layers` property. You can also create a new fill style layer and add it to the style using a method such as `-[MGLStyle addLayer:]`. - - + + ### Example + + ```swift + let layer = MGLFillStyleLayer(identifier: "parks", source: parks) + layer.sourceLayerIdentifier = "parks" + layer.fillColor = MGLStyleValue(rawValue: .green) + layer.predicate = NSPredicate(format: "type == %@", "national-park") + mapView.style.addLayer(layer) + ``` */ @interface MGLFillStyleLayer : MGLVectorStyleLayer diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index c3371aa2a7..f049ae1db1 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -87,8 +87,21 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) { otherwise, find it using the `MGLStyle.layers` property. You can also create a new line style layer and add it to the style using a method such as `-[MGLStyle addLayer:]`. - - + + ### Example + + ```swift + let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails) + layer.sourceLayerIdentifier = "trails" + layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [ + 14: MGLStyleValue(rawValue: 2), + 18: MGLStyleValue(rawValue: 20), + ]) + layer.lineColor = MGLStyleValue(rawValue: .brown) + layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round)) + layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking") + mapView.style.addLayer(layer) + ``` */ @interface MGLLineStyleLayer : MGLVectorStyleLayer diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterSource.h index 3efd84f383..cd95e85c5b 100644 --- a/platform/darwin/src/MGLRasterSource.h +++ b/platform/darwin/src/MGLRasterSource.h @@ -35,8 +35,19 @@ extern const MGLTileSourceOption MGLTileSourceOptionTileSize; `MGLRasterSource` object that you can use to initialize new style layers. You can also add and remove sources dynamically using methods such as `-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`. - - + + ### Example + + ```swift + let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .tileSize: 512, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) ``` */ @interface MGLRasterSource : MGLTileSource diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h index 7b53eebf96..45ab25a8f1 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.h +++ b/platform/darwin/src/MGLRasterStyleLayer.h @@ -23,8 +23,14 @@ NS_ASSUME_NONNULL_BEGIN otherwise, find it using the `MGLStyle.layers` property. You can also create a new raster style layer and add it to the style using a method such as `-[MGLStyle addLayer:]`. - - + + ### Example + + ```swift + let layer = MGLRasterStyleLayer(identifier: "clouds", source: source) + layer.rasterOpacity = MGLStyleValue(rawValue: 0.5) + mapView.style.addLayer(layer) + ``` */ @interface MGLRasterStyleLayer : MGLForegroundStyleLayer diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h index 0eb454437b..30e299d2b1 100644 --- a/platform/darwin/src/MGLShapeSource.h +++ b/platform/darwin/src/MGLShapeSource.h @@ -74,8 +74,18 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance; Any vector style layer initialized with a shape source should have a `nil` value in its `sourceLayerIdentifier` property. - - + + ### Example + + ```swift + var coordinates: [CLLocationCoordinate2D] = [ + CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42), + CLLocationCoordinate2D(latitude: 38.91, longitude: -77.04), + ] + let polyline = MGLPolylineFeature(coordinates: &coordinates, count: UInt(coordinates.count)) + let shape = MGLShapeCollectionFeature(shapes: [polyline]) + let source = MGLShapeSource(identifier: "lines", shape: shape, options: nil) + mapView.style.addSource(source) ``` */ @interface MGLShapeSource : MGLSource diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs index ac95022ea7..17529b8f9d 100644 --- a/platform/darwin/src/MGLStyleLayer.h.ejs +++ b/platform/darwin/src/MGLStyleLayer.h.ejs @@ -67,8 +67,11 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(property.name) %>) { otherwise, find it using the `MGLStyle.layers` property. You can also create a new <%- type %> style layer and add it to the style using a method such as `-[MGLStyle addLayer:]`. - - + + ### Example + + ```swift + ``` */ <% } -%> @interface MGL<%- camelize(type) %>StyleLayer : MGL<%- diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index 052d67617a..ca34698159 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -260,8 +260,21 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) { otherwise, find it using the `MGLStyle.layers` property. You can also create a new symbol style layer and add it to the style using a method such as `-[MGLStyle addLayer:]`. - - + + ### Example + + ```swift + let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois) + layer.sourceLayerIdentifier = "pois" + layer.iconImageName = MGLStyleValue(rawValue: "coffee") + layer.iconScale = MGLStyleValue(rawValue: 0.5) + layer.textField = MGLStyleValue(rawValue: "{name}") + layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0))) + layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left)) + layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left)) + layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee") + mapView.style.addLayer(layer) + ``` */ @interface MGLSymbolStyleLayer : MGLVectorStyleLayer diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorSource.h index ba8f075b5a..aa867adb6c 100644 --- a/platform/darwin/src/MGLVectorSource.h +++ b/platform/darwin/src/MGLVectorSource.h @@ -24,8 +24,19 @@ NS_ASSUME_NONNULL_BEGIN (extent × 2) − 1, inclusive. Any vector style layer initialized with a vector source must have a non-`nil` value in its `sourceLayerIdentifier` property. - - + + ### Example + + ```swift + let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + ``` */ @interface MGLVectorSource : MGLTileSource diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h index 50e56d8643..d33494c3e4 100644 --- a/platform/darwin/src/MGLVectorStyleLayer.h +++ b/platform/darwin/src/MGLVectorStyleLayer.h @@ -59,7 +59,10 @@ NS_ASSUME_NONNULL_BEGIN
  • NSContainsPredicateOperatorType (CONTAINS)
  • - To test whether a feature has or lacks a specific attribute, compare the attribute to `NULL` or `NIL`. Predicates created using the `+[NSPredicate predicateWithValue:]` method are also supported. String operators and custom operators are not supported. + To test whether a feature has or lacks a specific attribute, compare the + attribute to `NULL` or `NIL`. Predicates created using the + `+[NSPredicate predicateWithValue:]` method are also supported. String + operators and custom operators are not supported. For details about the predicate format string syntax, consult the “Predicate Format String Syntax” chapter of the @@ -130,8 +133,19 @@ NS_ASSUME_NONNULL_BEGIN style attributes and also `hyphen-minus` and `tag:subtag`. However, you must use `%K` in the format string to represent these variables: `@"%K == 'LineString'", @"$type"`. - - + + ### Example + + To filter the layer to include only the features whose `index` attribute is 5 + or 10 and whose `ele` attribute is at least 1,500, you could create an + `NSCompoundPredicate` along these lines: + + ```swift + let layer = MGLLineStyleLayer(identifier: "contour", source: terrain) + layer.sourceLayerIdentifier = "contours" + layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0") + mapView.style.addLayer(layer) + ``` */ @property (nonatomic, nullable) NSPredicate *predicate; diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift new file mode 100644 index 0000000000..9243924328 --- /dev/null +++ b/platform/darwin/test/MGLDocumentationExampleTests.swift @@ -0,0 +1,209 @@ +import XCTest +import Mapbox +#if os(iOS) + import UIKit +#else + import Cocoa +#endif + +/** + Test cases that ensure the inline examples in the project documentation + compile. + + To add an example: + 1. Add a test case named in the form testMGLClass or testMGLClass$method. + 2. Wrap the code you'd like to appear in the documentation within the + following comment blocks: + ``` + //#-example-code + ... + //#-end-example-code + ``` + 3. Insert an empty Swift code block inside the header file where you'd like the + example code to be inserted. + 4. Run `make darwin-update-examples` to extract example code from the test + method below and insert it into the header. + */ +class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate { + var mapView: MGLMapView! + var styleLoadingExpectation: XCTestExpectation! + + override func setUp() { + super.setUp() + let styleURL = Bundle(for: MGLDocumentationExampleTests.self).url(forResource: "one-liner", withExtension: "json") + mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: 256, height: 256), styleURL: styleURL) + mapView.delegate = self + styleLoadingExpectation = expectation(description: "Map view should finish loading style") + waitForExpectations(timeout: 1, handler: nil) + } + + override func tearDown() { + mapView = nil + styleLoadingExpectation = nil + super.tearDown() + } + + func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) { + styleLoadingExpectation.fulfill() + } + + func testMGLShapeSource() { + //#-example-code + var coordinates: [CLLocationCoordinate2D] = [ + CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42), + CLLocationCoordinate2D(latitude: 38.91, longitude: -77.04), + ] + let polyline = MGLPolylineFeature(coordinates: &coordinates, count: UInt(coordinates.count)) + let shape = MGLShapeCollectionFeature(shapes: [polyline]) + let source = MGLShapeSource(identifier: "lines", shape: shape, options: nil) + mapView.style.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style.source(withIdentifier: "lines")) + } + + func testMGLRasterSource() { + //#-example-code + let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .tileSize: 512, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style.source(withIdentifier: "clouds")) + } + + func testMGLVectorSource() { + //#-example-code + let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + //#-end-example-code + + XCTAssertNotNil(mapView.style.source(withIdentifier: "pois")) + } + + func testMGLCircleStyleLayer() { + let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(population) + + //#-example-code + let layer = MGLCircleStyleLayer(identifier: "circles", source: population) + layer.sourceLayerIdentifier = "population" + layer.circleColor = MGLStyleValue(rawValue: .green) + layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [ + 12: MGLStyleValue(rawValue: 2), + 22: MGLStyleValue(rawValue: 180) + ]) + layer.circleOpacity = MGLStyleValue(rawValue: 0.7) + layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "circles")) + } + + func testMGLLineStyleLayer() { + let trails = MGLVectorSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(trails) + + //#-example-code + let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails) + layer.sourceLayerIdentifier = "trails" + layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [ + 14: MGLStyleValue(rawValue: 2), + 18: MGLStyleValue(rawValue: 20), + ]) + layer.lineColor = MGLStyleValue(rawValue: .brown) + layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round)) + layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "trails-path")) + } + + func testMGLFillStyleLayer() { + let parks = MGLVectorSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(parks) + + //#-example-code + let layer = MGLFillStyleLayer(identifier: "parks", source: parks) + layer.sourceLayerIdentifier = "parks" + layer.fillColor = MGLStyleValue(rawValue: .green) + layer.predicate = NSPredicate(format: "type == %@", "national-park") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "parks")) + } + + func testMGLSymbolStyleLayer() { + let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(pois) + + //#-example-code + let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois) + layer.sourceLayerIdentifier = "pois" + layer.iconImageName = MGLStyleValue(rawValue: "coffee") + layer.iconScale = MGLStyleValue(rawValue: 0.5) + layer.textField = MGLStyleValue(rawValue: "{name}") + #if os(macOS) + var vector = CGVector(dx: 10, dy: 0) + layer.textTranslate = MGLStyleValue(rawValue: NSValue(bytes: &vector, objCType: "{CGVector=dd}")) + #else + layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0))) + #endif + layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left)) + layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left)) + layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "coffeeshops")) + } + + func testMGLRasterStyleLayer() { + let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ + .minimumZoomLevel: 9, + .maximumZoomLevel: 16, + .tileSize: 512, + .attributionInfos: [ + MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) + ] + ]) + mapView.style.addSource(source) + + //#-example-code + let layer = MGLRasterStyleLayer(identifier: "clouds", source: source) + layer.rasterOpacity = MGLStyleValue(rawValue: 0.5) + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "clouds")) + } + + func testMGLVectorStyleLayer$predicate() { + let terrain = MGLVectorSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!) + mapView.style.addSource(terrain) + + //#-example-code + let layer = MGLLineStyleLayer(identifier: "contour", source: terrain) + layer.sourceLayerIdentifier = "contours" + layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0") + mapView.style.addLayer(layer) + //#-end-example-code + + XCTAssertNotNil(mapView.style.layer(withIdentifier: "contour")) + } +} diff --git a/platform/darwin/test/MGLStyleLayerTests.m b/platform/darwin/test/MGLStyleLayerTests.m index 590d6eda7f..66bdc0df0b 100644 --- a/platform/darwin/test/MGLStyleLayerTests.m +++ b/platform/darwin/test/MGLStyleLayerTests.m @@ -10,6 +10,7 @@ - (void)setUp { [super setUp]; + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; #if TARGET_OS_IPHONE UIApplication *app = [UIApplication sharedApplication]; UIViewController *vc = [[UIViewController alloc] init]; @@ -19,12 +20,17 @@ [vc.view addSubview:_mapView]; _mapView.delegate = self; #else - [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MGLStyleLayerTests" owner:self]; [windowController showWindow:nil]; #endif } +- (void)tearDown { + _mapView = nil; + + [super tearDown]; +} + - (void)testPropertyName:(NSString *)name isBoolean:(BOOL)isBoolean { NS_MUTABLE_ARRAY_OF(NSString *) *components = [name componentsSeparatedByString:@"-"].mutableCopy; if (isBoolean) { diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm index 55a5df08ca..bcad7ab508 100644 --- a/platform/darwin/test/MGLStyleTests.mm +++ b/platform/darwin/test/MGLStyleTests.mm @@ -1,3 +1,4 @@ +#import "MGLAccountManager.h" #import "MGLMapView.h" #import "MGLStyle_Private.h" #import "MGLOpenGLStyleLayer.h" @@ -36,9 +37,19 @@ - (void)setUp { [super setUp]; - + + [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"]; self.mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; - self.style = [[MGLStyle alloc] initWithMapView:self.mapView]; +} + +- (void)tearDown { + self.mapView = nil; + + [super tearDown]; +} + +- (MGLStyle *)style { + return self.mapView.style; } - (void)testUnversionedStyleURLs { @@ -174,18 +185,18 @@ - (void)testAddingLayersWithDuplicateIdentifiers { //Just some source MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]]; - [self.mapView.style addSource: source]; + [self.style addSource: source]; //Add initial layer MGLFillStyleLayer *initial = [[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]; - [self.mapView.style addLayer:initial]; + [self.style addLayer:initial]; //Try to add the duplicate - XCTAssertThrowsSpecificNamed([self.mapView.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); - XCTAssertThrowsSpecificNamed([self.mapView.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style addLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source]], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] belowLayer:initial],NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] aboveLayer:initial], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLFillStyleLayer alloc] initWithIdentifier:@"my-layer" source:source] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); + XCTAssertThrowsSpecificNamed([self.style insertLayer:[[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"my-layer"] atIndex:0], NSException, @"MGLRedundantLayerIdentifierException"); } - (NSString *)stringWithContentsOfStyleHeader { @@ -209,8 +220,8 @@ #endif XCTAssertNotNil(image); - [self.mapView.style setImage:image forName:imageName]; - MGLImage *styleImage = [self.mapView.style imageForName:imageName]; + [self.style setImage:image forName:imageName]; + MGLImage *styleImage = [self.style imageForName:imageName]; XCTAssertNotNil(styleImage); XCTAssertEqual(image.size.width, styleImage.size.width); @@ -218,29 +229,27 @@ } - (void)testLayersOrder { - [self.mapView setStyleURL:[MGLStyle streetsStyleURLWithVersion:8]]; - NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; NSURL *url = [NSURL fileURLWithPath:filePath]; MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:@"sourceID" URL:url options:nil]; - [self.mapView.style addSource:source]; + [self.style addSource:source]; MGLCircleStyleLayer *layer1 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer1" source:source]; - [self.mapView.style addLayer:layer1]; + [self.style addLayer:layer1]; MGLCircleStyleLayer *layer3 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer3" source:source]; - [self.mapView.style addLayer:layer3]; + [self.style addLayer:layer3]; MGLCircleStyleLayer *layer2 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer2" source:source]; - [self.mapView.style insertLayer:layer2 aboveLayer:layer1]; + [self.style insertLayer:layer2 aboveLayer:layer1]; MGLCircleStyleLayer *layer4 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer4" source:source]; - [self.mapView.style insertLayer:layer4 aboveLayer:layer3]; + [self.style insertLayer:layer4 aboveLayer:layer3]; MGLCircleStyleLayer *layer0 = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layer0" source:source]; - [self.mapView.style insertLayer:layer0 belowLayer:layer1]; + [self.style insertLayer:layer0 belowLayer:layer1]; - NSArray *layers = [self.mapView.style layers]; + NSArray *layers = [self.style layers]; XCTAssert([[layers[0] identifier] isEqualToString:layer0.identifier]); XCTAssert([[layers[1] identifier] isEqualToString:layer1.identifier]); diff --git a/platform/darwin/test/one-liner.json b/platform/darwin/test/one-liner.json new file mode 100644 index 0000000000..23c546181f --- /dev/null +++ b/platform/darwin/test/one-liner.json @@ -0,0 +1 @@ +{"version":8,"sources":{},"layers":[]} \ No newline at end of file diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md index 94ff49ee1b..f7bc0cc415 100644 --- a/platform/ios/DEVELOPING.md +++ b/platform/ios/DEVELOPING.md @@ -118,6 +118,22 @@ To add a localization to the iOS SDK: 1. In the Project navigator, expand each .strings and .stringsdict file in the project. An additional version for your localization should be listed; translate it. Translate everything on the right side of the equals sign. Leave the left side and any comments unmodified. See Apple’s documentation on the [.strings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html) and [.stringsdict](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) formats. 1. You’re already most of the way towards localizing the macOS SDK too – consider [completing that localization](../macos/DEVELOPING.md#adding-a-localization). +### Adding a code example + +To add an example code listing to the documentation for a class or class member: + +1. Add a test method named in the form `testMGLClass` or `testMGLClass$method` + to [MGLDocumentationExampleTests](test/MGLDocumentationExampleTests.swift). + Wrap the code you’d like to appear in the documentation within + `//#-example-code` and `//#-end-example-code` comments. +1. Insert the code listings into the headers: + +```bash +make darwin-update-examples +``` + +[SourceKitten](https://github.com/jpsim/SourceKitten/) is required and will be installed automatically using Homebrew. + ## Testing `make ios-test` builds and runs unit tests of cross-platform code as well as the SDK. diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index ebcf3a55cb..8d96bcf497 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -228,6 +228,7 @@ DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2CB1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */; }; DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */; }; + DA35D0881E1A6309007DED41 /* one-liner.json in Resources */ = {isa = PBXBuildFile; fileRef = DA35D0871E1A6309007DED41 /* one-liner.json */; }; DA6408DB1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA6408DC1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */; }; @@ -617,7 +618,7 @@ 554180411D2E97DE00012372 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 55D8C9941D0F133500F42F10 /* config.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = config.xcconfig; path = ../../build/ios/config.xcconfig; sourceTree = ""; }; 55D8C9951D0F18CE00F42F10 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; - 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLDocumentationExampleTests.swift; sourceTree = ""; }; + 6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = ""; }; 7E016D7C1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolyline+MGLAdditions.h"; sourceTree = ""; }; 7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = ""; }; 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = ""; }; @@ -669,6 +670,7 @@ DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLAdditions.h"; sourceTree = ""; }; DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+MGLAdditions.m"; sourceTree = ""; }; DA35A2D11CCAB25200E826B2 /* jazzy.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = jazzy.yml; sourceTree = ""; }; + DA35D0871E1A6309007DED41 /* one-liner.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "one-liner.json"; path = "../../darwin/test/one-liner.json"; sourceTree = ""; }; DA4A26961CB6E795000B7809 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DA6408D91DA4E7D300908C90 /* MGLVectorStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorStyleLayer.h; sourceTree = ""; }; DA6408DA1DA4E7D300908C90 /* MGLVectorStyleLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLVectorStyleLayer.m; sourceTree = ""; }; @@ -1110,6 +1112,7 @@ DA2E88601CC0382C00F24E7B /* MGLStyleTests.mm */, DA2E88551CC036F400F24E7B /* Info.plist */, DA2784FB1DF02FF4001D5B8D /* Media.xcassets */, + DA35D0871E1A6309007DED41 /* one-liner.json */, ); name = "SDK Tests"; path = test; @@ -1706,7 +1709,6 @@ DA8847CE1CBAF91600AB86E3 /* Frameworks */, DA8847CF1CBAF91600AB86E3 /* Headers */, DA8847D01CBAF91600AB86E3 /* Resources */, - 64E5BF321E09D729005223F7 /* Add Examples to Documentation */, ); buildRules = ( ); @@ -1741,7 +1743,6 @@ DAA4E4101CBB71D400178DFB /* Frameworks */, DAA4E4111CBB71D400178DFB /* CopyFiles */, DABFB85C1CBE99DE00D62B32 /* Headers */, - 6421B07A1E09EA4B00AF169B /* Add Examples to Documentation */, ); buildRules = ( ); @@ -1869,6 +1870,7 @@ files = ( DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */, 353BAEF71D646370009A8DA9 /* amsterdam.geojson in Resources */, + DA35D0881E1A6309007DED41 /* one-liner.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1934,37 +1936,6 @@ }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - 6421B07A1E09EA4B00AF169B /* Add Examples to Documentation */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Add Examples to Documentation"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "node \"${SRCROOT}/scripts/add-examples-to-docs.js\""; - }; - 64E5BF321E09D729005223F7 /* Add Examples to Documentation */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Add Examples to Documentation"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "node \"${SRCROOT}/scripts/add-examples-to-docs.js\""; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ DA1DC9461CB6C1C2006E619F /* Sources */ = { isa = PBXSourcesBuildPhase; diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 1f1e48fce5..0a14cc3792 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -11,6 +11,8 @@ head: | objc: Yes skip_undocumented: Yes hide_documentation_coverage: Yes +umbrella_header: src/Mapbox.h +framework_root: ../darwin/src custom_categories: - name: Guides diff --git a/platform/ios/scripts/add-examples-to-docs.js b/platform/ios/scripts/add-examples-to-docs.js deleted file mode 100644 index 7be755e2c6..0000000000 --- a/platform/ios/scripts/add-examples-to-docs.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -const fs = require('fs'); - -const examples = fs.readFileSync(`${__dirname}/../test/MGLDocumentationExampleTests.swift`, 'utf8'); - -// Regex extracts the following block -// /*---BEGIN EXAMPLE: MGLStyleSource---*/ -// /* Frontmatter to describe the example */ -// let sampleCode: String? -// /*---END EXAMPLE---*/ -// -// into the following regex groups: -// 1 (token): " MGLStyleSource" -// 2 (frontmatter): "/* Frontmatter to describe the example */" -// 3 (sample code): "let sampleCode: String?" -const exampleRegex = /\/\*---BEGIN EXAMPLE:(.*)---\*\/\s*(\/\*+[\s\S]*?\*+\/)?([\s\S]*?)\/\*---END EXAMPLE---\*\//gm; - -var path = `${process.env.TARGET_BUILD_DIR}/${process.env.PUBLIC_HEADERS_FOLDER_PATH}`; - -console.log("Installing examples..."); - -var match; -while ((match = exampleRegex.exec(examples)) !== null) { - const token = match[1].trim(); - const className = token.split('.')[0]; - - const frontmatter = (match[2] || '') - .replace(/\/\*+/g, '') // Remove block comment /** - .replace(/\*+\//g, '') // Remove block comment end */ - .trim() - .replace(/\n {8,9}/g, '\n'); // Remove leading whitespace (8-9 spaces incl block comment) - - const exampleCode = match[3] - .trim() - .replace(/\n {8}/g, '\n'); // Remove leading whitespace (8 spaces) - - // Generate example text - var exampleText = "### Example\n\n"; - if (frontmatter.length > 0) { - exampleText += `${frontmatter}\n\n`; - } - exampleText += "```swift\n" + exampleCode + "\n```"; - exampleText = exampleText.replace(/\n/g, '\n '); - - const placeholderRegex = new RegExp(``); - - // check if file exists at path - const filename = `${path}/${className}.h`; - - if (fs.existsSync(filename)) { - const file = fs.readFileSync(filename, 'utf8'); - // Check for example placeholder in file & update file if found - if (placeholderRegex.test(file)) { - console.log("Updating example:", filename); - fs.writeFileSync(filename, file.replace(placeholderRegex, exampleText)); - } else if (file.indexOf(exampleText) === -1) { - console.log(`Placeholder "${token}" missing:`, filename); - } else { - console.log(`Example "${token}" already replaced.`); - } - } else if (token !== "ExampleToken") { - console.log("Error file doesn't exist:", filename); - } -} diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index 634f4de5dc..ec349d592d 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -35,16 +35,11 @@ cp -r platform/ios/docs/img "${OUTPUT}/img" DEFAULT_THEME="platform/darwin/docs/theme" THEME=${JAZZY_THEME:-$DEFAULT_THEME} -DEFAULT_FRAMEWORK_PATH="build/ios/pkg/dynamic/Mapbox.framework" -FRAMEWORK_PATH=${FRAMEWORK_PATH:-$DEFAULT_FRAMEWORK_PATH} - jazzy \ --config platform/ios/jazzy.yml \ --sdk iphonesimulator \ --github-file-prefix https://github.com/mapbox/mapbox-gl-native/tree/${BRANCH} \ --module-version ${SHORT_VERSION} \ - --framework-root ${FRAMEWORK_PATH} \ - --umbrella-header "${FRAMEWORK_PATH}/Headers/Mapbox.h" \ --readme ${README} \ --documentation="platform/ios/docs/guides/*.md" \ --root-url https://www.mapbox.com/ios-sdk/api/${RELEASE_VERSION}/ \ diff --git a/platform/ios/test/MGLDocumentationExampleTests.swift b/platform/ios/test/MGLDocumentationExampleTests.swift deleted file mode 100644 index 0d97cfeb35..0000000000 --- a/platform/ios/test/MGLDocumentationExampleTests.swift +++ /dev/null @@ -1,204 +0,0 @@ -import XCTest -import Mapbox -import UIKit - -/** - Test cases that ensure the inline examples in the project documentation - compile. - - There is a run script build phase for the dynamic & static iOS targets - that invokes `/platform/ios/scrips/add-examples-to-docs.js`. This script - will pull example code out of this test file and replace the corresponding - placeholder comment in the built header files. - - Adding examples: - 1. Add a test case below - 2. Wrap the code you'd like to appear in the documentation within the - following comment blocks: - `/*---BEGIN EXAMPLE: ExampleToken---*/` - ... - `/*---END EXAMPLE---*/` - 3. Insert a comment `` inside the header file - where you'd like the example code to be inserted - */ -class MGLDocumentationExampleTests: XCTestCase { - var mapView: MGLMapView! - - override func setUp() { - super.setUp() - self.mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: 256, height: 256)) - } - - override func tearDown() { - self.mapView = nil - super.tearDown() - } - - // MGLShapeSource - func testMGLShapeSourceExample() { - /*---BEGIN EXAMPLE: MGLShapeSource---*/ - var coordinates: [CLLocationCoordinate2D] = [ - CLLocationCoordinate2D(latitude: 37.77, longitude: -122.42), - CLLocationCoordinate2D(latitude: 38.91, longitude: -77.04), - ] - let polyline = MGLPolylineFeature(coordinates: &coordinates, count: UInt(coordinates.count)) - let shape = MGLShapeCollectionFeature(shapes: [polyline]) - let source = MGLShapeSource(identifier: "lines", shape: shape, options: nil) - mapView.style.addSource(source) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.source(withIdentifier: "lines")) - } - - // MGLRasterSource - func testMGLRasterSourceExample() { - /*---BEGIN EXAMPLE: MGLRasterSource---*/ - let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ - .minimumZoomLevel: 9, - .maximumZoomLevel: 16, - .tileSize: 512, - .attributionInfos: [ - MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) - ] - ]) - mapView.style.addSource(source) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.source(withIdentifier: "clouds")) - } - - // MGLVectorSource - func testMGLVectorSource() { - /*---BEGIN EXAMPLE: MGLVectorSource---*/ - let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [ - .minimumZoomLevel: 9, - .maximumZoomLevel: 16, - .attributionInfos: [ - MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) - ] - ]) - mapView.style.addSource(source) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.source(withIdentifier: "pois")) - } - - // MGLCircleStyleLayer - func testMGLCircleStyleLayerExample() { - let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!) - mapView.style.addSource(population) - - /*---BEGIN EXAMPLE: MGLCircleStyleLayer---*/ - let layer = MGLCircleStyleLayer(identifier: "circles", source: population) - layer.sourceLayerIdentifier = "population" - layer.circleColor = MGLStyleValue(rawValue: UIColor.green) - layer.circleRadius = MGLStyleValue(interpolationBase: 1.75, stops: [ - 12: MGLStyleValue(rawValue: 2), - 22: MGLStyleValue(rawValue: 180) - ]) - layer.circleOpacity = MGLStyleValue(rawValue: 0.7) - layer.predicate = NSPredicate(format: "%K == %@", "marital-status", "married") - mapView.style.addLayer(layer) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.layer(withIdentifier: "circles")) - } - - // MGLLineStyleLayer - func testMGLLineStyleLayerExample() { - let trails = MGLVectorSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!) - mapView.style.addSource(trails) - - /*---BEGIN EXAMPLE: MGLLineStyleLayer---*/ - let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails) - layer.sourceLayerIdentifier = "trails" - layer.lineWidth = MGLStyleValue(interpolationBase: 1.5, stops: [ - 14: MGLStyleValue(rawValue: 2), - 18: MGLStyleValue(rawValue: 20), - ]) - layer.lineColor = MGLStyleValue(rawValue: UIColor.brown) - layer.lineCap = MGLStyleValue(rawValue: NSValue(mglLineCap: .round)) - layer.predicate = NSPredicate(format: "%K == %@", "trail-type", "mountain-biking") - mapView.style.addLayer(layer) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.layer(withIdentifier: "trails-path")) - } - - // MGLFillStyleLayer - func testMGLFillStyleLayerExample() { - let parks = MGLVectorSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!) - mapView.style.addSource(parks) - - /*---BEGIN EXAMPLE: MGLFillStyleLayer---*/ - let layer = MGLFillStyleLayer(identifier: "parks", source: parks) - layer.sourceLayerIdentifier = "parks" - layer.fillColor = MGLStyleValue(rawValue: UIColor.green) - layer.predicate = NSPredicate(format: "type == %@", "national-park") - mapView.style.addLayer(layer) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.layer(withIdentifier: "parks")) - } - - // MGLSymbolStyleLayer - func testMGLSymbolStyleLayerExample() { - let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!) - mapView.style.addSource(pois) - - /*---BEGIN EXAMPLE: MGLSymbolStyleLayer---*/ - let layer = MGLSymbolStyleLayer(identifier: "coffeeshops", source: pois) - layer.sourceLayerIdentifier = "pois" - layer.iconImageName = MGLStyleValue(rawValue: "coffee") - layer.iconScale = MGLStyleValue(rawValue: 0.5) - layer.textField = MGLStyleValue(rawValue: "{name}") - layer.textTranslate = MGLStyleValue(rawValue: NSValue(cgVector: CGVector(dx: 10, dy: 0))) - layer.textJustification = MGLStyleValue(rawValue: NSValue(mglTextJustification: .left)) - layer.textAnchor = MGLStyleValue(rawValue: NSValue(mglTextAnchor: .left)) - layer.predicate = NSPredicate(format: "%K == %@", "venue-type", "coffee") - mapView.style.addLayer(layer) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.layer(withIdentifier: "coffeeshops")) - } - - // MGLRasterStyleLayer - func testMGLRasterStyleLayer() { - let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [ - .minimumZoomLevel: 9, - .maximumZoomLevel: 16, - .tileSize: 512, - .attributionInfos: [ - MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com")) - ] - ]) - mapView.style.addSource(source) - - /*---BEGIN EXAMPLE: MGLRasterStyleLayer---*/ - let layer = MGLRasterStyleLayer(identifier: "clouds", source: source) - layer.rasterOpacity = MGLStyleValue(rawValue: 0.5) - mapView.style.addLayer(layer) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.layer(withIdentifier: "clouds")) - } - - // MGLVectorStyleLayer.predicate - func testMGLVectorStyleLayer() { - let terrain = MGLVectorSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!) - mapView.style.addSource(terrain) - - /*---BEGIN EXAMPLE: MGLVectorStyleLayer.predicate---*/ - /** - To create a filter with the logic `(index == 10 || index == 5) && ele >= 200`, - you could create a predicate using `NSCompoundPredicate` along these lines: - */ - let layer = MGLLineStyleLayer(identifier: "contour", source: terrain) - layer.sourceLayerIdentifier = "contours" - layer.predicate = NSPredicate(format: "(index == 10 || index == 5) && ele >= 1500.0") - mapView.style.addLayer(layer) - /*---END EXAMPLE---*/ - - XCTAssertNotNil(mapView.style.layer(withIdentifier: "contour")) - } -} diff --git a/platform/macos/DEVELOPING.md b/platform/macos/DEVELOPING.md index 71eb7995c8..823ad4656b 100644 --- a/platform/macos/DEVELOPING.md +++ b/platform/macos/DEVELOPING.md @@ -95,6 +95,32 @@ To add a localization to the macOS SDK: 1. In the Project navigator, expand each .strings and .stringsdict file in the project. An additional version for your localization should be listed; translate it. Translate everything on the right side of the equals sign. Leave the left side and any comments unmodified. See Apple’s documentation on the [.strings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html) and [.stringsdict](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) formats. 1. You’re already most of the way towards localizing the iOS SDK too – consider [completing that localization](../ios/DEVELOPING.md#adding-a-localization). +### Adding a code example + +To add an example code listing to the documentation for a class or class member: + +1. Add a test method named in the form `testMGLClass` or `testMGLClass$method` + to [MGLDocumentationExampleTests](test/MGLDocumentationExampleTests.swift). + Wrap the code you’d like to appear in the documentation within + `//#-example-code` and `//#-end-example-code` comments. +1. Insert the code listings into the headers: + +```bash +make darwin-update-examples +``` + +[SourceKitten](https://github.com/jpsim/SourceKitten/) is required and will be installed automatically using Homebrew. + +## Testing + +`make macos-test` builds and runs unit tests of cross-platform code as well as the SDK. + +To instead run the cross-platform tests in Xcode instead of on the command line: + +1. Run `make xproj` to set up the workspace. +1. Change the scheme to “mbgl-test” and press Command-R to run core unit tests. +1. Change the scheme to “CI” and press Command-U to run SDK integration tests. + ## Access tokens The demo applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). You will be prompted for this access token the first time you launch the demo application. diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 56872a1b19..e4657596cf 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -68,6 +68,7 @@ DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */; }; DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */; }; DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DA2784FD1DF03060001D5B8D /* Media.xcassets */; }; + DA29875A1E1A4290002299F5 /* MGLDocumentationExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */; }; DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */; }; DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; }; @@ -80,6 +81,7 @@ DA35A2C21CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */; }; DA35A2CF1CCAAED300E826B2 /* NSValue+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA35A2D01CCAAED300E826B2 /* NSValue+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */; }; + DA35D08A1E1A631B007DED41 /* one-liner.json in Resources */ = {isa = PBXBuildFile; fileRef = DA35D0891E1A631B007DED41 /* one-liner.json */; }; DA551B821DB496AC0009AFAF /* MGLTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; }; DA551B831DB496AC0009AFAF /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */; }; DA551B841DB496AC0009AFAF /* MGLTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA551B811DB496AC0009AFAF /* MGLTileSource.mm */; }; @@ -321,6 +323,7 @@ DA2207BA1DC076930002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = ""; }; DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLStyleValueTests.swift; sourceTree = ""; }; DA2784FD1DF03060001D5B8D /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Media.xcassets; path = ../../darwin/test/Media.xcassets; sourceTree = ""; }; + DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MGLDocumentationExampleTests.swift; path = ../../darwin/test/MGLDocumentationExampleTests.swift; sourceTree = ""; }; DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLStyleLayerTests.xib; sourceTree = ""; }; DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCoordinateFormatter.h; sourceTree = ""; }; DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCoordinateFormatter.m; sourceTree = ""; }; @@ -333,6 +336,7 @@ DA35A2C11CCA9F4A00E826B2 /* MGLClockDirectionFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLClockDirectionFormatterTests.m; path = ../../darwin/test/MGLClockDirectionFormatterTests.m; sourceTree = ""; }; DA35A2CD1CCAAED300E826B2 /* NSValue+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLAdditions.h"; sourceTree = ""; }; DA35A2CE1CCAAED300E826B2 /* NSValue+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSValue+MGLAdditions.m"; sourceTree = ""; }; + DA35D0891E1A631B007DED41 /* one-liner.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "one-liner.json"; path = "../../darwin/test/one-liner.json"; sourceTree = ""; }; DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource.h; sourceTree = ""; }; DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource_Private.h; sourceTree = ""; }; DA551B811DB496AC0009AFAF /* MGLTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSource.mm; sourceTree = ""; }; @@ -886,6 +890,7 @@ 3526EABC1DF9B19800006B43 /* MGLCodingTests.m */, DA35A2B51CCA14D700E826B2 /* MGLCompassDirectionFormatterTests.m */, DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */, + DA2987591E1A4290002299F5 /* MGLDocumentationExampleTests.swift */, DD58A4C71D822C6200E1F038 /* MGLExpressionTests.mm */, DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */, DAE6C3C81CC34BD800DB3429 /* MGLGeometryTests.mm */, @@ -896,6 +901,7 @@ DAE6C3CC1CC34BD800DB3429 /* MGLStyleTests.mm */, DAE6C33A1CC30DB200DB3429 /* Info.plist */, DA2784FD1DF03060001D5B8D /* Media.xcassets */, + DA35D0891E1A631B007DED41 /* one-liner.json */, ); name = "SDK Tests"; path = test; @@ -1216,6 +1222,7 @@ 35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */, DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */, DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */, + DA35D08A1E1A631B007DED41 /* one-liner.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1326,6 +1333,7 @@ DA87A99E1DC9DC2100810D09 /* MGLPredicateTests.mm in Sources */, DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */, DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.m in Sources */, + DA29875A1E1A4290002299F5 /* MGLDocumentationExampleTests.swift in Sources */, DAE6C3D31CC34C9900DB3429 /* MGLOfflinePackTests.m in Sources */, DA87A9A51DCACC5000810D09 /* MGLLineStyleLayerTests.m in Sources */, DA87A9A31DCACC5000810D09 /* MGLRasterStyleLayerTests.m in Sources */, -- cgit v1.2.1 From 0fac9d5674453f587a4c86f71b06da668f8cae27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Fri, 23 Dec 2016 17:47:51 -0800 Subject: [ios, macos] Added guide for working with GeoJSON --- .../docs/guides/Working with GeoJSON Data.md | 89 ++++++++++++++++++++++ platform/ios/jazzy.yml | 1 + platform/ios/scripts/document.sh | 2 +- platform/macos/docs/Info.plist Keys.md | 17 ----- platform/macos/docs/guides/Info.plist Keys.md | 17 +++++ platform/macos/jazzy.yml | 1 + platform/macos/scripts/document.sh | 2 +- 7 files changed, 110 insertions(+), 19 deletions(-) create mode 100644 platform/darwin/docs/guides/Working with GeoJSON Data.md delete mode 100644 platform/macos/docs/Info.plist Keys.md create mode 100644 platform/macos/docs/guides/Info.plist Keys.md (limited to 'platform') diff --git a/platform/darwin/docs/guides/Working with GeoJSON Data.md b/platform/darwin/docs/guides/Working with GeoJSON Data.md new file mode 100644 index 0000000000..0fffed06dd --- /dev/null +++ b/platform/darwin/docs/guides/Working with GeoJSON Data.md @@ -0,0 +1,89 @@ +# Working with GeoJSON Data + +This SDK offers several ways to work with [GeoJSON](http://geojson.org/) files. +GeoJSON is a standard file format for representing geographic data. + +## Adding a GeoJSON file to the map + +You can use +[Mapbox Studio’s Datasets editor](https://www.mapbox.com/studio/datasets/) to +upload a GeoJSON file and include it in your custom map style. The GeoJSON data +will be hosted on Mapbox servers. When a user loads your style, the SDK +automatically loads the GeoJSON data for display. + +Alternatively, if you need to host the GeoJSON file elsewhere or bundle it with +your application, you can use a GeoJSON file as the basis of an `MGLShapeSource` +object. Pass the file’s URL into the +`-[MGLShapeSource initWithIdentifier:URL:options:]` initializer and add the +shape source to the map using the `-[MGLStyle addSource:]` method. The URL may +be a local file URL, an HTTP URL, or an HTTPS URL. + +Once you’ve added the GeoJSON file to the map via an `MGLShapeSource` object, +you can configure the appearance of its data and control what data is visible +using `MGLStyleLayer` objects, you can +[access the data programmatically](#Extracting GeoJSON data from the map). + +## Converting GeoJSON data into shape objects + +If you have GeoJSON data in the form of source code (also known as “GeoJSON +text”), you can convert it into an `MGLShape`, `MGLFeature`, or +`MGLShapeCollectionFeature` object that the `MGLShapeSource` class understands +natively. First, create an `NSData` object out of the source code string or file +contents, then pass that data object into the +`+[MGLShape shapeWithData:encoding:error:]` method. Finally, you can pass the +resulting shape or feature object into the +`-[MGLShapeSource initWithIdentifier:shape:options:]` initializer and add it to +the map, or you can use the object and its properties to power non-map-related +functionality in your application. + +## Extracting GeoJSON data from the map + +Any `MGLShape`, `MGLFeature`, or `MGLShapeCollectionFeature` object has an +`-[MGLShape geoJSONDataUsingEncoding:]` method that you can use to create a +GeoJSON source code representation of the object. You can extract a feature +object from the map using a method such as +`-[MGLMapView visibleFeaturesAtPoint:]`. + +## About GeoJSON deserialization + +The process of converting GeoJSON text into `MGLShape`, `MGLFeature`, or +`MGLShapeCollectionFeature` objects is known as “GeoJSON deserialization”. +GeoJSON geometries, features, and feature collections are known in this SDK as +shapes, features, and shape collection features, respectively. + +Each GeoJSON object type corresponds to a type provided by either this SDK or +the Core Location framework: + +GeoJSON object type | SDK type +--------------------|--------- +`Position` (longitude, latitude) | `CLLocationCoordinate2D` (latitude, longitude) +`Point` | `MGLPointAnnotation` +`MultiPoint` | `MGLPointCollection` +`LineString` | `MGLPolyline` +`MultiLineString` | `MGLMultiPolyline` +`Polygon` | `MGLPolygon` +Linear ring | `MGLPolygon.coordinates`, `MGLPolygon.interiorPolygons` +`MultiPolygon` | `MGLMultiPolygon` +`GeometryCollection` | `MGLShapeCollection` +`Feature` | `MGLFeature` +`FeatureCollection` | `MGLShapeCollectionFeature` + +A `Feature` object in GeoJSON corresponds to an instance of an `MGLShape` +subclass conforming to the `MGLFeature` protocol. There is a distinct +`MGLFeature`-conforming class for each type of geometry that a GeoJSON feature +can contain. This allows features to be used as shapes where convenient. For +example, some features can be added to a map view as annotations. + +In contrast to the GeoJSON standard, it is possible for `MGLShape` subclasses +other than `MGLPointAnnotation` to straddle the antimeridian. + +The following GeoJSON data types correspond straightforwardly to Foundation data +types when they occur as feature identifiers or property values: + +GeoJSON data type | Objective-C representation | Swift representation +-------------------|----------------------------|--------------------- +`null` | `NSNull` | `NSNull` +`true`, `false` | `NSNumber.boolValue` | `NSNumber.boolValue` +Integer | `NSNumber.unsignedLongLongValue`, `NSNumber.longLongValue` | `NSNumber.uint64Value`, `NSNumber.int64Value` +Floating-point number | `NSNumber.doubleValue` | `NSNumber.doubleValue` +String | `NSString` | `String` diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 0a14cc3792..2473d0d1a3 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -21,6 +21,7 @@ custom_categories: - Runtime Styling - Working with Mapbox Studio - Info.plist Keys + - Working with GeoJSON Data - name: Maps children: - MGLAccountManager diff --git a/platform/ios/scripts/document.sh b/platform/ios/scripts/document.sh index ec349d592d..d66742a33f 100755 --- a/platform/ios/scripts/document.sh +++ b/platform/ios/scripts/document.sh @@ -41,7 +41,7 @@ jazzy \ --github-file-prefix https://github.com/mapbox/mapbox-gl-native/tree/${BRANCH} \ --module-version ${SHORT_VERSION} \ --readme ${README} \ - --documentation="platform/ios/docs/guides/*.md" \ + --documentation="platform/{darwin,ios}/docs/guides/*.md" \ --root-url https://www.mapbox.com/ios-sdk/api/${RELEASE_VERSION}/ \ --theme ${THEME} \ --output ${OUTPUT} diff --git a/platform/macos/docs/Info.plist Keys.md b/platform/macos/docs/Info.plist Keys.md deleted file mode 100644 index a92b6fe296..0000000000 --- a/platform/macos/docs/Info.plist Keys.md +++ /dev/null @@ -1,17 +0,0 @@ -# Info.plist Keys - -The Mapbox macOS SDK supports custom `Info.plist` keys in your application in order to configure various settings. - -## MGLMapboxAccessToken - -Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/) to be used by all instances of `MGLMapView` in the current application. - -Mapbox-hosted vector tiles and styles require an API access token, which you can obtain from the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). Access tokens associate requests to Mapbox’s vector tile and style APIs with your Mapbox account. They also deter other developers from using your styles without your permission. - -As an alternative, you can use `+[MGLAccountManager setAccessToken:]` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private. - -## MGLMapboxAPIBaseURL - -Use this key if you need to customize the API base URL used throughout the SDK. If unset, the default Mapbox API is used. - -The default value is `https://api.mapbox.com`. diff --git a/platform/macos/docs/guides/Info.plist Keys.md b/platform/macos/docs/guides/Info.plist Keys.md new file mode 100644 index 0000000000..f61ad8c7a7 --- /dev/null +++ b/platform/macos/docs/guides/Info.plist Keys.md @@ -0,0 +1,17 @@ +# Info.plist Keys + +The Mapbox macOS SDK supports custom `Info.plist` keys in your application in order to configure various settings. + +## MGLMapboxAccessToken + +Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/) to be used by all instances of `MGLMapView` in the current application. + +Mapbox-hosted vector tiles and styles require an API access token, which you can obtain from the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). Access tokens associate requests to Mapbox’s vector tile and style APIs with your Mapbox account. They also deter other developers from using your styles without your permission. + +As an alternative, you can use `+[MGLAccountManager setAccessToken:]` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private. + +## MGLMapboxAPIBaseURL + +Use this key if you need to customize the API base URL used throughout the SDK. If unset, the default Mapbox API is used. + +The default value is `https://api.mapbox.com`. diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index 27202968ef..f237ba72bc 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -17,6 +17,7 @@ custom_categories: - name: Guides children: - Info.plist Keys + - Working with GeoJSON Data - name: Maps children: - MGLAccountManager diff --git a/platform/macos/scripts/document.sh b/platform/macos/scripts/document.sh index d03ad91674..22b7685c7e 100755 --- a/platform/macos/scripts/document.sh +++ b/platform/macos/scripts/document.sh @@ -38,7 +38,7 @@ jazzy \ --github-file-prefix https://github.com/mapbox/mapbox-gl-native/tree/${BRANCH} \ --module-version ${SHORT_VERSION} \ --readme ${README} \ - --documentation="platform/macos/docs/Info.plist Keys.md" \ + --documentation="platform/{darwin,macos}/docs/guides/*.md" \ --theme platform/darwin/docs/theme \ --output ${OUTPUT} # https://github.com/realm/jazzy/issues/411 -- cgit v1.2.1 From 7e120e32b824d7d3deda2448f67cfe346c5ff29d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sat, 24 Dec 2016 11:38:47 -0800 Subject: [ios, macos] Added guide for style authors Added a guide to orient JSON stylesheet authors and Mapbox Studio users around the runtime styling API. An introductory section details the many considerations for designing a robust style for use with iOS and macOS devices. --- platform/darwin/docs/guides/For Style Authors.md | 234 +++++++++++++++++++++ .../darwin/docs/guides/For Style Authors.md.ejs | 208 ++++++++++++++++++ platform/darwin/scripts/generate-style-code.js | 19 +- platform/ios/jazzy.yml | 1 + platform/macos/jazzy.yml | 1 + 5 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 platform/darwin/docs/guides/For Style Authors.md create mode 100644 platform/darwin/docs/guides/For Style Authors.md.ejs (limited to 'platform') diff --git a/platform/darwin/docs/guides/For Style Authors.md b/platform/darwin/docs/guides/For Style Authors.md new file mode 100644 index 0000000000..b7de36516b --- /dev/null +++ b/platform/darwin/docs/guides/For Style Authors.md @@ -0,0 +1,234 @@ + +# Information for Style Authors + +A _style_ defines a map view’s content and appearance. If you’ve authored a +style using +[Mapbox Studio’s Styles editor](https://www.mapbox.com/studio/styles/) or as +JSON in a text editor, you can use that style in this SDK and manipulate it +afterwards in code. This document provides information you can use to ensure a +seamless transition from Mapbox Studio to your application. + +## Designing for the platform + +When designing your style, consider the context in which your application shows +the style. There are a number of considerations specific to iOS and macOS that +may not be obvious when designing your style in Mapbox Studio on the Web. A map +view is essentially a graphical user interface element, so many of same issues +in user interface design also apply when designing a map style. + +### Color + +Ensure sufficient contrast in your application’s user interface when your map +style is present. Standard user interface elements such as toolbars and sidebars +often overlap the map view with a translucent, blurred background, so make sure +the contents of these elements remain legible with the map view underneath. On +iOS, the user location annotation view, the attribution button, any buttons in +callout views, and any items in the navigation bar are influenced by your +application’s tint color, so choose a tint color that constrasts well with your +map style. If you intend your style to be used in the dark, consider the impact +that the Night Shift mode on iOS may have on your style’s colors. + +### Typography and graphics + +Choose font and icon sizes appropriate to the device: iOS devices have smaller +screens than the typical browser window in which you would use Mapbox Studio, +and your user’s viewing distance may be shorter than on a desktop computer. Some +of your users may use the Dynamic Type and Accessibility Text features on iOS +and macOS to increase the size of all text on the device. You can use the +[runtime styling API](#manipulating-the-style-at-runtime) to adjust your style’s +font and icon sizes accordingly. + +Design sprite images and choose font weights that look crisp on both +standard-resolution displays and Retina displays. This SDK supports the same +resolutions as the operating system it runs on. On iOS, standard-resolution +displays are limited to older devices that your application may or may not +support, depending on its minimum deployment target. On macOS, +standard-resolution displays are often found on external monitors. + +### Interactivity + +Pay attention to whether elements of your style appear to be interactive. An +icon with a shadow or shading effect may appear to be clickable on macOS. +Likewise, a text label may look like a tappable button on iOS merely due to +matching your application’s tint color or the default blue tint color. You can +actually make an icon or text label interactive by installing a gesture +recognizer and performing feature querying (e.g., +`-[MGLMapView visibleFeaturesAtPoint:]`) to get details about the selected +feature. + +Make sure your users can easily distinguish any interactive elements from the +surrounding map, such as pins, the user location annotation view, or a route +line. On iOS, avoid relying on hover effects to indicate interactive elements, +and leave enough room between interactive elements to accommodate imprecise +tapping gestures. + +For more information about user interface design, consult Apple’s +_Human Interface Guidelines_ document for +[iOS](https://developer.apple.com/ios/human-interface-guidelines/) or +[macOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). + +## Setting the style + +You set an `MGLMapView` object’s style either in code, by setting the +`MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style +URL” inspectable. The URL must point to a local or remote style JSON file. The +style JSON file format is defined by the +[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). This +SDK supports the functionality defined by version 8 of the specification unless +otherwise noted in the +[style specification documentation](https://www.mapbox.com/mapbox-gl-style-spec/). + +## Manipulating the style at runtime + +The _runtime styling API_ enables you to modify every aspect of a style +dynamically as a user interacts with your application. The style itself is +represented at runtime by an `MGLStyle` object, which provides access to various +`MGLSource` and `MGLStyleLayer` objects that represent content sources and style +layers, respectively. + +The names of runtime styling classes and properties on iOS and macOS are +generally consistent with the style specification and Mapbox Studio’s Styles +editor. Any exceptions are listed in this document. + +To avoid conflicts with Objective-C keywords or Cocoa terminology, this SDK uses +the following terms for concepts defined in the style specification: + +In the style specification | In the SDK +---------------------------|--------- +class | style class +filter | predicate +id | identifier +image | style image +layer | style layer +property | attribute +SDF icon | template image +source | content source + +## Specifying the map’s content + +Each source defined by a style JSON file is represented at runtime by a content +source object that you can use to initialize new style layers. The content +source object is a member of one of the following subclasses of `MGLSource`: + +In style JSON | In the SDK +--------------|----------- +`geojson` | `MGLShapeSource` +`raster` | `MGLRasterSource` +`vector` | `MGLVectorSource` + +`image` and `video` sources are not supported. + +## Configuring the map content’s appearance + +Each layer defined by the style JSON file is represented at runtime by a style +layer object, which you can use to refine the map’s appearance. The style layer +object is a member of one of the following subclasses of `MGLStyleLayer`: + +In style JSON | In the SDK +--------------|----------- +`fill` | `MGLFillStyleLayer` +`line` | `MGLLineStyleLayer` +`symbol` | `MGLSymbolStyleLayer` +`circle` | `MGLCircleStyleLayer` +`raster` | `MGLRasterStyleLayer` +`background` | `MGLBackgroundStyleLayer` + +You configure layout and paint attributes by setting properties on these style +layer objects. The property names generally correspond to the style JSON +properties, except for the use of camelCase instead of kebab-case. Properties +whose names differ from the style specification are listed below: + +### Fill style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`fill-antialias` | `MGLFillStyleLayer.fillAntialiased` | `MGLFillStyleLayer.isFillAntialiased` + +### Line style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`line-dasharray` | `MGLLineStyleLayer.lineDashPattern` | `MGLLineStyleLayer.lineDashPattern` + +### Symbol style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`icon-allow-overlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` +`icon-ignore-placement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` +`icon-image` | `MGLSymbolStyleLayer.iconImageName` | `MGLSymbolStyleLayer.iconImageName` +`icon-optional` | `MGLSymbolStyleLayer.iconOptional` | `MGLSymbolStyleLayer.isIconOptional` +`icon-rotate` | `MGLSymbolStyleLayer.iconRotation` | `MGLSymbolStyleLayer.iconRotation` +`icon-size` | `MGLSymbolStyleLayer.iconScale` | `MGLSymbolStyleLayer.iconScale` +`icon-keep-upright` | `MGLSymbolStyleLayer.keepsIconUpright` | `MGLSymbolStyleLayer.keepsIconUpright` +`text-keep-upright` | `MGLSymbolStyleLayer.keepsTextUpright` | `MGLSymbolStyleLayer.keepsTextUpright` +`text-max-angle` | `MGLSymbolStyleLayer.maximumTextAngle` | `MGLSymbolStyleLayer.maximumTextAngle` +`text-max-width` | `MGLSymbolStyleLayer.maximumTextWidth` | `MGLSymbolStyleLayer.maximumTextWidth` +`symbol-avoid-edges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` +`text-allow-overlap` | `MGLSymbolStyleLayer.textAllowsOverlap` | `MGLSymbolStyleLayer.textAllowsOverlap` +`text-ignore-placement` | `MGLSymbolStyleLayer.textIgnoresPlacement` | `MGLSymbolStyleLayer.textIgnoresPlacement` +`text-justify` | `MGLSymbolStyleLayer.textJustification` | `MGLSymbolStyleLayer.textJustification` +`text-optional` | `MGLSymbolStyleLayer.textOptional` | `MGLSymbolStyleLayer.isTextOptional` +`text-rotate` | `MGLSymbolStyleLayer.textRotation` | `MGLSymbolStyleLayer.textRotation` + +### Raster style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`raster-brightness-max` | `MGLRasterStyleLayer.maximumRasterBrightness` | `MGLRasterStyleLayer.maximumRasterBrightness` +`raster-brightness-min` | `MGLRasterStyleLayer.minimumRasterBrightness` | `MGLRasterStyleLayer.minimumRasterBrightness` +`raster-hue-rotate` | `MGLRasterStyleLayer.rasterHueRotation` | `MGLRasterStyleLayer.rasterHueRotation` + +## Setting attribute values + +Each property representing a layout or paint attribute is set to an +`MGLStyleValue` object, which is either an `MGLStyleConstantValue` object (for +constant values) or an `MGLStyleFunction` object (for zoom level functions). The +style value object is a container for the raw value or function parameters that +you want the attribute to be set to. + +In contrast to the JSON type that the style specification defines for each +layout or paint property, the style value object often contains a more specific +Foundation or Cocoa type. General rules for attribute types are listed below. +Pay close attention to the SDK documentation for the attribute you want to set. + +In style JSON | In Objective-C | In Swift +--------------|-----------------------|--------- +Color | `NSColor` (macOS)
    `UIColor` (iOS) | `NSColor` (macOS)
    `UIColor` (iOS) +Enum | `NSValue` (see `NSValue(MGLAdditions)`) | `NSValue` (see `NSValue(MGLAdditions)`) +String | `NSString` | `String` +Boolean | `NSNumber.boolValue` | `NSNumber.boolValue` +Number | `NSNumber.floatValue` | `NSNumber.floatValue` +Array (`-dasharray`) | `NSArray` | `[NSNumber]` +Array (`-font`) | `NSArray` | `[String]` +Array (`-offset`, `-translate`) | `CGVector` | `CGVector` +Array (`-padding`) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) + +## Filtering sources + +You can filter a shape or vector source by setting the +`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a +table of style JSON operators and the corresponding operators used in the +predicate format string: + +In style JSON | In the format string +--------------------------|--------------------- +`["has", key]` | `key != nil` +`["!has", key]` | `key == nil` +`["==", key, value]` | `key == value` +`["!=", key, value]` | `key != value` +`[">", key, value]` | `key > value` +`[">=", key, value]` | `key >= value` +`["<", key, value]` | `key < value` +`["<=", key, value]` | `key <= value` +`["in", key, v0, …, vn]` | `key IN {v0, …, vn}` +`["!in", key, v0, …, vn]` | `NOT key IN {v0, …, vn}` +`["all", f0, …, fn]` | `p0 AND … AND pn` +`["any", f0, …, fn]` | `p0 OR … OR pn` +`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)` + +See the `MGLVectorStyleLayer.predicate` documentation for a full description of +the supported operators and operand types. diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs new file mode 100644 index 0000000000..32cef9344b --- /dev/null +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -0,0 +1,208 @@ +<% + const types = locals.types; + const renamedProperties = locals.renamedProperties; +-%> + +# Information for Style Authors + +A _style_ defines a map view’s content and appearance. If you’ve authored a +style using +[Mapbox Studio’s Styles editor](https://www.mapbox.com/studio/styles/) or as +JSON in a text editor, you can use that style in this SDK and manipulate it +afterwards in code. This document provides information you can use to ensure a +seamless transition from Mapbox Studio to your application. + +## Designing for the platform + +When designing your style, consider the context in which your application shows +the style. There are a number of considerations specific to iOS and macOS that +may not be obvious when designing your style in Mapbox Studio on the Web. A map +view is essentially a graphical user interface element, so many of same issues +in user interface design also apply when designing a map style. + +### Color + +Ensure sufficient contrast in your application’s user interface when your map +style is present. Standard user interface elements such as toolbars and sidebars +often overlap the map view with a translucent, blurred background, so make sure +the contents of these elements remain legible with the map view underneath. On +iOS, the user location annotation view, the attribution button, any buttons in +callout views, and any items in the navigation bar are influenced by your +application’s tint color, so choose a tint color that constrasts well with your +map style. If you intend your style to be used in the dark, consider the impact +that the Night Shift mode on iOS may have on your style’s colors. + +### Typography and graphics + +Choose font and icon sizes appropriate to the device: iOS devices have smaller +screens than the typical browser window in which you would use Mapbox Studio, +and your user’s viewing distance may be shorter than on a desktop computer. Some +of your users may use the Dynamic Type and Accessibility Text features on iOS +and macOS to increase the size of all text on the device. You can use the +[runtime styling API](#manipulating-the-style-at-runtime) to adjust your style’s +font and icon sizes accordingly. + +Design sprite images and choose font weights that look crisp on both +standard-resolution displays and Retina displays. This SDK supports the same +resolutions as the operating system it runs on. On iOS, standard-resolution +displays are limited to older devices that your application may or may not +support, depending on its minimum deployment target. On macOS, +standard-resolution displays are often found on external monitors. + +### Interactivity + +Pay attention to whether elements of your style appear to be interactive. An +icon with a shadow or shading effect may appear to be clickable on macOS. +Likewise, a text label may look like a tappable button on iOS merely due to +matching your application’s tint color or the default blue tint color. You can +actually make an icon or text label interactive by installing a gesture +recognizer and performing feature querying (e.g., +`-[MGLMapView visibleFeaturesAtPoint:]`) to get details about the selected +feature. + +Make sure your users can easily distinguish any interactive elements from the +surrounding map, such as pins, the user location annotation view, or a route +line. On iOS, avoid relying on hover effects to indicate interactive elements, +and leave enough room between interactive elements to accommodate imprecise +tapping gestures. + +For more information about user interface design, consult Apple’s +_Human Interface Guidelines_ document for +[iOS](https://developer.apple.com/ios/human-interface-guidelines/) or +[macOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). + +## Setting the style + +You set an `MGLMapView` object’s style either in code, by setting the +`MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style +URL” inspectable. The URL must point to a local or remote style JSON file. The +style JSON file format is defined by the +[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). This +SDK supports the functionality defined by version 8 of the specification unless +otherwise noted in the +[style specification documentation](https://www.mapbox.com/mapbox-gl-style-spec/). + +## Manipulating the style at runtime + +The _runtime styling API_ enables you to modify every aspect of a style +dynamically as a user interacts with your application. The style itself is +represented at runtime by an `MGLStyle` object, which provides access to various +`MGLSource` and `MGLStyleLayer` objects that represent content sources and style +layers, respectively. + +The names of runtime styling classes and properties on iOS and macOS are +generally consistent with the style specification and Mapbox Studio’s Styles +editor. Any exceptions are listed in this document. + +To avoid conflicts with Objective-C keywords or Cocoa terminology, this SDK uses +the following terms for concepts defined in the style specification: + +In the style specification | In the SDK +---------------------------|--------- +class | style class +filter | predicate +id | identifier +image | style image +layer | style layer +property | attribute +SDF icon | template image +source | content source + +## Specifying the map’s content + +Each source defined by a style JSON file is represented at runtime by a content +source object that you can use to initialize new style layers. The content +source object is a member of one of the following subclasses of `MGLSource`: + +In style JSON | In the SDK +--------------|----------- +`geojson` | `MGLShapeSource` +`raster` | `MGLRasterSource` +`vector` | `MGLVectorSource` + +`image` and `video` sources are not supported. + +## Configuring the map content’s appearance + +Each layer defined by the style JSON file is represented at runtime by a style +layer object, which you can use to refine the map’s appearance. The style layer +object is a member of one of the following subclasses of `MGLStyleLayer`: + +In style JSON | In the SDK +--------------|----------- +<% for (const type of types) { -%> +`<%- type %>` | `MGL<%- camelize(type) %>StyleLayer` +<% } -%> + +You configure layout and paint attributes by setting properties on these style +layer objects. The property names generally correspond to the style JSON +properties, except for the use of camelCase instead of kebab-case. Properties +whose names differ from the style specification are listed below: +<% for (const type in renamedProperties) { -%> +<% if (renamedProperties.hasOwnProperty(type)) { -%> + +### <%- camelize(type) %> style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +<% for (const name in renamedProperties[type]) { -%> +<% if (renamedProperties[type].hasOwnProperty(name)) { -%> +`<%- originalPropertyName(renamedProperties[type][name]) %>` | `MGL<%- camelize(type) %>StyleLayer.<%- objCName(renamedProperties[type][name]) %>` | `MGL<%- camelize(type) %>StyleLayer.<%- objCGetter(renamedProperties[type][name]) %>` +<% } -%> +<% } -%> +<% } -%> +<% } -%> + +## Setting attribute values + +Each property representing a layout or paint attribute is set to an +`MGLStyleValue` object, which is either an `MGLStyleConstantValue` object (for +constant values) or an `MGLStyleFunction` object (for zoom level functions). The +style value object is a container for the raw value or function parameters that +you want the attribute to be set to. + +In contrast to the JSON type that the style specification defines for each +layout or paint property, the style value object often contains a more specific +Foundation or Cocoa type. General rules for attribute types are listed below. +Pay close attention to the SDK documentation for the attribute you want to set. + +In style JSON | In Objective-C | In Swift +--------------|-----------------------|--------- +Color | `NSColor` (macOS)
    `UIColor` (iOS) | `NSColor` (macOS)
    `UIColor` (iOS) +Enum | `NSValue` (see `NSValue(MGLAdditions)`) | `NSValue` (see `NSValue(MGLAdditions)`) +String | `NSString` | `String` +Boolean | `NSNumber.boolValue` | `NSNumber.boolValue` +Number | `NSNumber.floatValue` | `NSNumber.floatValue` +Array (`-dasharray`) | `NSArray` | `[NSNumber]` +Array (`-font`) | `NSArray` | `[String]` +Array (`-offset`, `-translate`) | `CGVector` | `CGVector` +Array (`-padding`) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) + +## Filtering sources + +You can filter a shape or vector source by setting the +`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a +table of style JSON operators and the corresponding operators used in the +predicate format string: + +In style JSON | In the format string +--------------------------|--------------------- +`["has", key]` | `key != nil` +`["!has", key]` | `key == nil` +`["==", key, value]` | `key == value` +`["!=", key, value]` | `key != value` +`[">", key, value]` | `key > value` +`[">=", key, value]` | `key >= value` +`["<", key, value]` | `key < value` +`["<=", key, value]` | `key <= value` +`["in", key, v0, …, vn]` | `key IN {v0, …, vn}` +`["!in", key, v0, …, vn]` | `NOT key IN {v0, …, vn}` +`["all", f0, …, fn]` | `p0 AND … AND pn` +`["any", f0, …, fn]` | `p0 OR … OR pn` +`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)` + +See the `MGLVectorStyleLayer.predicate` documentation for a full description of +the supported operators and operand types. diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 46f55c889c..9d42972ab5 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -370,6 +370,7 @@ const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.m.ejs', 'utf8'), { strict: true}); const categoryH = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs', 'utf8'), { strict: true}); const categoryM = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs', 'utf8'), { strict: true}); +const guideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true }); const layers = Object.keys(spec.layer.type.values).map((type) => { const layoutProperties = Object.keys(spec[`layout_${type}`]).reduce((memo, name) => { @@ -416,14 +417,21 @@ ${macosComment}${decl} var allLayoutProperties = []; var allPaintProperties = []; var allTypes = []; +var allRenamedProperties = {}; -for (var layer of layers) { +for (let layer of layers) { allLayoutProperties.push(layer.layoutProperties); allPaintProperties.push(layer.paintProperties); allTypes.push(layer.type); - const containsEnumerationProperties = _.filter(layer.layoutProperties, function(property){ return property["type"] === "enum"; }).length || _.filter(layer.paintProperties, function(property){ return property["type"] === "enum"; }).length; - layer.containsEnumerationProperties = containsEnumerationProperties; + let properties = _.concat(layer.layoutProperties, layer.paintProperties); + layer.containsEnumerationProperties = _.some(properties, prop => prop.type === "enum"); + let renamedProperties = {}; + _.assign(renamedProperties, _.filter(properties, prop => 'original' in prop || 'getter' in prop)); + if (!_.isEmpty(renamedProperties)) { + allRenamedProperties[layer.type] = renamedProperties; + } + fs.writeFileSync(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.h`, duplicatePlatformDecls(layerH(layer))); fs.writeFileSync(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.mm`, layerM(layer)); fs.writeFileSync(`platform/darwin/test/${prefix}${camelize(layer.type)}${suffix}Tests.m`, testLayers(layer)); @@ -438,3 +446,8 @@ fs.writeFileSync(`platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm` layoutProperties: _.flatten(allLayoutProperties), paintProperties: _.flatten(allPaintProperties) })); + +fs.writeFileSync(`platform/darwin/docs/guides/For Style Authors.md`, guideMD({ + renamedProperties: allRenamedProperties, + types: allTypes, +})); diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 2473d0d1a3..1ba341bd17 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -22,6 +22,7 @@ custom_categories: - Working with Mapbox Studio - Info.plist Keys - Working with GeoJSON Data + - For Style Authors - name: Maps children: - MGLAccountManager diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index f237ba72bc..6f88c01bc6 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -18,6 +18,7 @@ custom_categories: children: - Info.plist Keys - Working with GeoJSON Data + - For Style Authors - name: Maps children: - MGLAccountManager -- cgit v1.2.1 From 5b03318c6fa885e35826e61753ce6fbcbd79b512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Sat, 24 Dec 2016 20:15:45 -0800 Subject: [ios, macos] Compare source options to specs --- platform/darwin/docs/guides/For Style Authors.md | 41 +++++++++++++++++++++- .../darwin/docs/guides/For Style Authors.md.ejs | 41 +++++++++++++++++++++- platform/darwin/src/MGLShapeSource.h | 20 +++++++++++ platform/darwin/src/MGLTileSource.h | 20 +++++++++++ 4 files changed, 120 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/darwin/docs/guides/For Style Authors.md b/platform/darwin/docs/guides/For Style Authors.md index b7de36516b..927dd18392 100644 --- a/platform/darwin/docs/guides/For Style Authors.md +++ b/platform/darwin/docs/guides/For Style Authors.md @@ -70,7 +70,7 @@ _Human Interface Guidelines_ document for [iOS](https://developer.apple.com/ios/human-interface-guidelines/) or [macOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). -## Setting the style +## Applying your style You set an `MGLMapView` object’s style either in code, by setting the `MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style @@ -121,6 +121,45 @@ In style JSON | In the SDK `image` and `video` sources are not supported. +### Tile sources + +Raster and vector sources may be defined in TileJSON configuration files. This +SDK supports the properties defined in the style specification, which are a +subset of the keys defined in version 2.1.0 of the +[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0) +specification. As an alternative to authoring a custom TileJSON file, you may +supply various tile source options when creating a raster or vector source. +These options are detailed in the `MGLTileSourceOption` documentation: + +In style JSON | In TileJSON | In the SDK +--------------|---------------|----------- +`url` | — | `configurationURL` parameter in `-[MGLTileSource initWithIdentifier:configurationURL:]` +`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]` +`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel` +`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel` +`tileSize` | — | `MGLTileSourceOptionTileSize` +`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security) +`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem` + +### Shape sources + +Shape sources also accept various options. These options are detailed in the +`MGLShapeSourceOption` documentation: + +In style JSON | In the SDK +-----------------|----------- +`data` | `url` parameter in `-[MGLShapeSource initWithIdentifier:URL:options:]` +`maxzoom` | `MGLShapeSourceOptionMaximumZoomLevel` +`buffer` | `MGLShapeSourceOptionBuffer` +`tolerance` | `MGLShapeSourceOptionSimplificationTolerance` +`cluster` | `MGLShapeSourceOptionClustered` +`clusterRadius` | `MGLShapeSourceOptionClusterRadius` +`clusterMaxZoom` | `MGLShapeSourceOptionMaximumZoomLevelForClustering` + +To create a shape source from local GeoJSON data, first +[convert the GeoJSON data into a shape](working-with-geojson-data.html#converting-geojson-data-into-shape-objects), +then use the `-[MGLShapeSource initWithIdentifier:shape:options:]` method. + ## Configuring the map content’s appearance Each layer defined by the style JSON file is represented at runtime by a style diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index 32cef9344b..a56f48acae 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -74,7 +74,7 @@ _Human Interface Guidelines_ document for [iOS](https://developer.apple.com/ios/human-interface-guidelines/) or [macOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). -## Setting the style +## Applying your style You set an `MGLMapView` object’s style either in code, by setting the `MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style @@ -125,6 +125,45 @@ In style JSON | In the SDK `image` and `video` sources are not supported. +### Tile sources + +Raster and vector sources may be defined in TileJSON configuration files. This +SDK supports the properties defined in the style specification, which are a +subset of the keys defined in version 2.1.0 of the +[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0) +specification. As an alternative to authoring a custom TileJSON file, you may +supply various tile source options when creating a raster or vector source. +These options are detailed in the `MGLTileSourceOption` documentation: + +In style JSON | In TileJSON | In the SDK +--------------|---------------|----------- +`url` | — | `configurationURL` parameter in `-[MGLTileSource initWithIdentifier:configurationURL:]` +`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]` +`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel` +`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel` +`tileSize` | — | `MGLTileSourceOptionTileSize` +`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security) +`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem` + +### Shape sources + +Shape sources also accept various options. These options are detailed in the +`MGLShapeSourceOption` documentation: + +In style JSON | In the SDK +-----------------|----------- +`data` | `url` parameter in `-[MGLShapeSource initWithIdentifier:URL:options:]` +`maxzoom` | `MGLShapeSourceOptionMaximumZoomLevel` +`buffer` | `MGLShapeSourceOptionBuffer` +`tolerance` | `MGLShapeSourceOptionSimplificationTolerance` +`cluster` | `MGLShapeSourceOptionClustered` +`clusterRadius` | `MGLShapeSourceOptionClusterRadius` +`clusterMaxZoom` | `MGLShapeSourceOptionMaximumZoomLevelForClustering` + +To create a shape source from local GeoJSON data, first +[convert the GeoJSON data into a shape](working-with-geojson-data.html#converting-geojson-data-into-shape-objects), +then use the `-[MGLShapeSource initWithIdentifier:shape:options:]` method. + ## Configuring the map content’s appearance Each layer defined by the style JSON file is represented at runtime by a style diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h index 30e299d2b1..a276864be7 100644 --- a/platform/darwin/src/MGLShapeSource.h +++ b/platform/darwin/src/MGLShapeSource.h @@ -16,6 +16,10 @@ typedef NSString *MGLShapeSourceOption NS_STRING_ENUM; An `NSNumber` object containing a Boolean enabling or disabling clustering. If the `shape` property contains point shapes, setting this option to `YES` clusters the points by radius into groups. The default value is `NO`. + + This attribute corresponds to the + cluster + source property in the Mapbox Style Specification. */ extern const MGLShapeSourceOption MGLShapeSourceOptionClustered; @@ -31,6 +35,10 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius; which to cluster points if clustering is enabled. Defaults to one zoom level less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the maximum zoom level, the shapes are not clustered. + + This attribute corresponds to the + clusterMaxZoom + source property in the Mapbox Style Specification. */ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering; @@ -38,6 +46,10 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForCluster An `NSNumber` object containing an integer; specifies the maximum zoom level at which to create vector tiles. A greater value produces greater detail at high zoom levels. The default value is 18. + + This attribute corresponds to the + maxzoom + source property in the Mapbox Style Specification. */ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel; @@ -46,6 +58,10 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel; buffer on each side. A value of 0 produces no buffer. A value of 512 produces a buffer as wide as the tile itself. Larger values produce fewer rendering artifacts near tile edges and slower performance. The default value is 128. + + This attribute corresponds to the + buffer + source property in the Mapbox Style Specification. */ extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer; @@ -53,6 +69,10 @@ extern const MGLShapeSourceOption MGLShapeSourceOptionBuffer; An `NSNumber` object containing a double; specifies the Douglas-Peucker simplification tolerance. A greater value produces simpler geometries and improves performance. The default value is 0.375. + + This attribute corresponds to the + tolerance + source property in the Mapbox Style Specification. */ extern const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance; diff --git a/platform/darwin/src/MGLTileSource.h b/platform/darwin/src/MGLTileSource.h index 12bc72538c..db5bc73338 100644 --- a/platform/darwin/src/MGLTileSource.h +++ b/platform/darwin/src/MGLTileSource.h @@ -19,6 +19,10 @@ typedef NSString *MGLTileSourceOption NS_STRING_ENUM; The value should be between 0 and 22, inclusive, and less than `MGLTileSourceOptionMaximumZoomLevel`, if specified. The default value for this option is 0. + + This option corresponds to the `minzoom` key in the + TileJSON + specification. */ extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel; @@ -29,6 +33,10 @@ extern const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel; The value should be between 0 and 22, inclusive, and less than `MGLTileSourceOptionMinimumZoomLevel`, if specified. The default value for this option is 22. + + This option corresponds to the `maxzoom` key in the + TileJSON + specification. */ extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel; @@ -41,6 +49,10 @@ extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel; By default, no attribution statements are displayed. If the `MGLTileSourceOptionAttributionInfos` option is specified, this option is ignored. + + This option corresponds to the `attribution` key in the + TileJSON + specification. */ extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString; @@ -60,6 +72,10 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos; By default, no attribution statements are displayed. If the `MGLTileSourceOptionAttributionInfos` option is specified, this option is ignored. + + This option corresponds to the `attribution` key in the + TileJSON + specification. */ extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString; @@ -79,6 +95,10 @@ extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos; the constants described in `MGLTileCoordinateSystem`. The default value for this option is `MGLTileCoordinateSystemXYZ`. + + This option corresponds to the `scheme` key in the + TileJSON + specification. */ extern const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem; -- cgit v1.2.1 From a1bea12444e7c68324c95ef8c082f558b39ca1ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Sat, 24 Dec 2016 22:23:08 -0800 Subject: [ios, macos] Split For Style Authors guide Information for Style Authors is now two separate guides, one for iOS and one for macOS. Both are compiled from the same template. Added language about rotation, tilting, and printing. --- platform/darwin/docs/guides/For Style Authors.md | 273 -------------------- .../darwin/docs/guides/For Style Authors.md.ejs | 121 ++++++--- platform/darwin/scripts/generate-style-code.js | 8 +- platform/ios/docs/guides/For Style Authors.md | 279 +++++++++++++++++++++ platform/macos/docs/guides/For Style Authors.md | 269 ++++++++++++++++++++ 5 files changed, 641 insertions(+), 309 deletions(-) delete mode 100644 platform/darwin/docs/guides/For Style Authors.md create mode 100644 platform/ios/docs/guides/For Style Authors.md create mode 100644 platform/macos/docs/guides/For Style Authors.md (limited to 'platform') diff --git a/platform/darwin/docs/guides/For Style Authors.md b/platform/darwin/docs/guides/For Style Authors.md deleted file mode 100644 index 927dd18392..0000000000 --- a/platform/darwin/docs/guides/For Style Authors.md +++ /dev/null @@ -1,273 +0,0 @@ - -# Information for Style Authors - -A _style_ defines a map view’s content and appearance. If you’ve authored a -style using -[Mapbox Studio’s Styles editor](https://www.mapbox.com/studio/styles/) or as -JSON in a text editor, you can use that style in this SDK and manipulate it -afterwards in code. This document provides information you can use to ensure a -seamless transition from Mapbox Studio to your application. - -## Designing for the platform - -When designing your style, consider the context in which your application shows -the style. There are a number of considerations specific to iOS and macOS that -may not be obvious when designing your style in Mapbox Studio on the Web. A map -view is essentially a graphical user interface element, so many of same issues -in user interface design also apply when designing a map style. - -### Color - -Ensure sufficient contrast in your application’s user interface when your map -style is present. Standard user interface elements such as toolbars and sidebars -often overlap the map view with a translucent, blurred background, so make sure -the contents of these elements remain legible with the map view underneath. On -iOS, the user location annotation view, the attribution button, any buttons in -callout views, and any items in the navigation bar are influenced by your -application’s tint color, so choose a tint color that constrasts well with your -map style. If you intend your style to be used in the dark, consider the impact -that the Night Shift mode on iOS may have on your style’s colors. - -### Typography and graphics - -Choose font and icon sizes appropriate to the device: iOS devices have smaller -screens than the typical browser window in which you would use Mapbox Studio, -and your user’s viewing distance may be shorter than on a desktop computer. Some -of your users may use the Dynamic Type and Accessibility Text features on iOS -and macOS to increase the size of all text on the device. You can use the -[runtime styling API](#manipulating-the-style-at-runtime) to adjust your style’s -font and icon sizes accordingly. - -Design sprite images and choose font weights that look crisp on both -standard-resolution displays and Retina displays. This SDK supports the same -resolutions as the operating system it runs on. On iOS, standard-resolution -displays are limited to older devices that your application may or may not -support, depending on its minimum deployment target. On macOS, -standard-resolution displays are often found on external monitors. - -### Interactivity - -Pay attention to whether elements of your style appear to be interactive. An -icon with a shadow or shading effect may appear to be clickable on macOS. -Likewise, a text label may look like a tappable button on iOS merely due to -matching your application’s tint color or the default blue tint color. You can -actually make an icon or text label interactive by installing a gesture -recognizer and performing feature querying (e.g., -`-[MGLMapView visibleFeaturesAtPoint:]`) to get details about the selected -feature. - -Make sure your users can easily distinguish any interactive elements from the -surrounding map, such as pins, the user location annotation view, or a route -line. On iOS, avoid relying on hover effects to indicate interactive elements, -and leave enough room between interactive elements to accommodate imprecise -tapping gestures. - -For more information about user interface design, consult Apple’s -_Human Interface Guidelines_ document for -[iOS](https://developer.apple.com/ios/human-interface-guidelines/) or -[macOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). - -## Applying your style - -You set an `MGLMapView` object’s style either in code, by setting the -`MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style -URL” inspectable. The URL must point to a local or remote style JSON file. The -style JSON file format is defined by the -[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). This -SDK supports the functionality defined by version 8 of the specification unless -otherwise noted in the -[style specification documentation](https://www.mapbox.com/mapbox-gl-style-spec/). - -## Manipulating the style at runtime - -The _runtime styling API_ enables you to modify every aspect of a style -dynamically as a user interacts with your application. The style itself is -represented at runtime by an `MGLStyle` object, which provides access to various -`MGLSource` and `MGLStyleLayer` objects that represent content sources and style -layers, respectively. - -The names of runtime styling classes and properties on iOS and macOS are -generally consistent with the style specification and Mapbox Studio’s Styles -editor. Any exceptions are listed in this document. - -To avoid conflicts with Objective-C keywords or Cocoa terminology, this SDK uses -the following terms for concepts defined in the style specification: - -In the style specification | In the SDK ----------------------------|--------- -class | style class -filter | predicate -id | identifier -image | style image -layer | style layer -property | attribute -SDF icon | template image -source | content source - -## Specifying the map’s content - -Each source defined by a style JSON file is represented at runtime by a content -source object that you can use to initialize new style layers. The content -source object is a member of one of the following subclasses of `MGLSource`: - -In style JSON | In the SDK ---------------|----------- -`geojson` | `MGLShapeSource` -`raster` | `MGLRasterSource` -`vector` | `MGLVectorSource` - -`image` and `video` sources are not supported. - -### Tile sources - -Raster and vector sources may be defined in TileJSON configuration files. This -SDK supports the properties defined in the style specification, which are a -subset of the keys defined in version 2.1.0 of the -[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0) -specification. As an alternative to authoring a custom TileJSON file, you may -supply various tile source options when creating a raster or vector source. -These options are detailed in the `MGLTileSourceOption` documentation: - -In style JSON | In TileJSON | In the SDK ---------------|---------------|----------- -`url` | — | `configurationURL` parameter in `-[MGLTileSource initWithIdentifier:configurationURL:]` -`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]` -`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel` -`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel` -`tileSize` | — | `MGLTileSourceOptionTileSize` -`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security) -`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem` - -### Shape sources - -Shape sources also accept various options. These options are detailed in the -`MGLShapeSourceOption` documentation: - -In style JSON | In the SDK ------------------|----------- -`data` | `url` parameter in `-[MGLShapeSource initWithIdentifier:URL:options:]` -`maxzoom` | `MGLShapeSourceOptionMaximumZoomLevel` -`buffer` | `MGLShapeSourceOptionBuffer` -`tolerance` | `MGLShapeSourceOptionSimplificationTolerance` -`cluster` | `MGLShapeSourceOptionClustered` -`clusterRadius` | `MGLShapeSourceOptionClusterRadius` -`clusterMaxZoom` | `MGLShapeSourceOptionMaximumZoomLevelForClustering` - -To create a shape source from local GeoJSON data, first -[convert the GeoJSON data into a shape](working-with-geojson-data.html#converting-geojson-data-into-shape-objects), -then use the `-[MGLShapeSource initWithIdentifier:shape:options:]` method. - -## Configuring the map content’s appearance - -Each layer defined by the style JSON file is represented at runtime by a style -layer object, which you can use to refine the map’s appearance. The style layer -object is a member of one of the following subclasses of `MGLStyleLayer`: - -In style JSON | In the SDK ---------------|----------- -`fill` | `MGLFillStyleLayer` -`line` | `MGLLineStyleLayer` -`symbol` | `MGLSymbolStyleLayer` -`circle` | `MGLCircleStyleLayer` -`raster` | `MGLRasterStyleLayer` -`background` | `MGLBackgroundStyleLayer` - -You configure layout and paint attributes by setting properties on these style -layer objects. The property names generally correspond to the style JSON -properties, except for the use of camelCase instead of kebab-case. Properties -whose names differ from the style specification are listed below: - -### Fill style layers - -In style JSON | In Objective-C | In Swift ---------------|----------------|--------- -`fill-antialias` | `MGLFillStyleLayer.fillAntialiased` | `MGLFillStyleLayer.isFillAntialiased` - -### Line style layers - -In style JSON | In Objective-C | In Swift ---------------|----------------|--------- -`line-dasharray` | `MGLLineStyleLayer.lineDashPattern` | `MGLLineStyleLayer.lineDashPattern` - -### Symbol style layers - -In style JSON | In Objective-C | In Swift ---------------|----------------|--------- -`icon-allow-overlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` -`icon-ignore-placement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` -`icon-image` | `MGLSymbolStyleLayer.iconImageName` | `MGLSymbolStyleLayer.iconImageName` -`icon-optional` | `MGLSymbolStyleLayer.iconOptional` | `MGLSymbolStyleLayer.isIconOptional` -`icon-rotate` | `MGLSymbolStyleLayer.iconRotation` | `MGLSymbolStyleLayer.iconRotation` -`icon-size` | `MGLSymbolStyleLayer.iconScale` | `MGLSymbolStyleLayer.iconScale` -`icon-keep-upright` | `MGLSymbolStyleLayer.keepsIconUpright` | `MGLSymbolStyleLayer.keepsIconUpright` -`text-keep-upright` | `MGLSymbolStyleLayer.keepsTextUpright` | `MGLSymbolStyleLayer.keepsTextUpright` -`text-max-angle` | `MGLSymbolStyleLayer.maximumTextAngle` | `MGLSymbolStyleLayer.maximumTextAngle` -`text-max-width` | `MGLSymbolStyleLayer.maximumTextWidth` | `MGLSymbolStyleLayer.maximumTextWidth` -`symbol-avoid-edges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` -`text-allow-overlap` | `MGLSymbolStyleLayer.textAllowsOverlap` | `MGLSymbolStyleLayer.textAllowsOverlap` -`text-ignore-placement` | `MGLSymbolStyleLayer.textIgnoresPlacement` | `MGLSymbolStyleLayer.textIgnoresPlacement` -`text-justify` | `MGLSymbolStyleLayer.textJustification` | `MGLSymbolStyleLayer.textJustification` -`text-optional` | `MGLSymbolStyleLayer.textOptional` | `MGLSymbolStyleLayer.isTextOptional` -`text-rotate` | `MGLSymbolStyleLayer.textRotation` | `MGLSymbolStyleLayer.textRotation` - -### Raster style layers - -In style JSON | In Objective-C | In Swift ---------------|----------------|--------- -`raster-brightness-max` | `MGLRasterStyleLayer.maximumRasterBrightness` | `MGLRasterStyleLayer.maximumRasterBrightness` -`raster-brightness-min` | `MGLRasterStyleLayer.minimumRasterBrightness` | `MGLRasterStyleLayer.minimumRasterBrightness` -`raster-hue-rotate` | `MGLRasterStyleLayer.rasterHueRotation` | `MGLRasterStyleLayer.rasterHueRotation` - -## Setting attribute values - -Each property representing a layout or paint attribute is set to an -`MGLStyleValue` object, which is either an `MGLStyleConstantValue` object (for -constant values) or an `MGLStyleFunction` object (for zoom level functions). The -style value object is a container for the raw value or function parameters that -you want the attribute to be set to. - -In contrast to the JSON type that the style specification defines for each -layout or paint property, the style value object often contains a more specific -Foundation or Cocoa type. General rules for attribute types are listed below. -Pay close attention to the SDK documentation for the attribute you want to set. - -In style JSON | In Objective-C | In Swift ---------------|-----------------------|--------- -Color | `NSColor` (macOS)
    `UIColor` (iOS) | `NSColor` (macOS)
    `UIColor` (iOS) -Enum | `NSValue` (see `NSValue(MGLAdditions)`) | `NSValue` (see `NSValue(MGLAdditions)`) -String | `NSString` | `String` -Boolean | `NSNumber.boolValue` | `NSNumber.boolValue` -Number | `NSNumber.floatValue` | `NSNumber.floatValue` -Array (`-dasharray`) | `NSArray` | `[NSNumber]` -Array (`-font`) | `NSArray` | `[String]` -Array (`-offset`, `-translate`) | `CGVector` | `CGVector` -Array (`-padding`) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) - -## Filtering sources - -You can filter a shape or vector source by setting the -`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a -table of style JSON operators and the corresponding operators used in the -predicate format string: - -In style JSON | In the format string ---------------------------|--------------------- -`["has", key]` | `key != nil` -`["!has", key]` | `key == nil` -`["==", key, value]` | `key == value` -`["!=", key, value]` | `key != value` -`[">", key, value]` | `key > value` -`[">=", key, value]` | `key >= value` -`["<", key, value]` | `key < value` -`["<=", key, value]` | `key <= value` -`["in", key, v0, …, vn]` | `key IN {v0, …, vn}` -`["!in", key, v0, …, vn]` | `NOT key IN {v0, …, vn}` -`["all", f0, …, fn]` | `p0 AND … AND pn` -`["any", f0, …, fn]` | `p0 OR … OR pn` -`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)` - -See the `MGLVectorStyleLayer.predicate` documentation for a full description of -the supported operators and operand types. diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index a56f48acae..0bd9bbecd9 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -1,4 +1,8 @@ <% + const os = locals.os; + const iOS = os === 'iOS'; + const macOS = os === 'macOS'; + const cocoaPrefix = iOS ? 'UI' : 'NS'; const types = locals.types; const renamedProperties = locals.renamedProperties; -%> @@ -15,64 +19,111 @@ JSON in a text editor, you can use that style in this SDK and manipulate it afterwards in code. This document provides information you can use to ensure a seamless transition from Mapbox Studio to your application. -## Designing for the platform +<% if (iOS) { -%> +## Designing for iOS +<% } else { -%> +## Designing for macOS +<% } -%> When designing your style, consider the context in which your application shows -the style. There are a number of considerations specific to iOS and macOS that -may not be obvious when designing your style in Mapbox Studio on the Web. A map -view is essentially a graphical user interface element, so many of same issues -in user interface design also apply when designing a map style. +the style. There are a number of considerations specific to <%- os %> that may +not be obvious when designing your style in Mapbox Studio on the Web. A map view +is essentially a graphical user interface element, so many of same issues in +user interface design also apply when designing a map style. ### Color Ensure sufficient contrast in your application’s user interface when your map -style is present. Standard user interface elements such as toolbars and sidebars -often overlap the map view with a translucent, blurred background, so make sure -the contents of these elements remain legible with the map view underneath. On -iOS, the user location annotation view, the attribution button, any buttons in +style is present. Standard user interface elements such as toolbars, sidebars, +and sheets often overlap the map view with a translucent, blurred background, so +make sure the contents of these elements remain legible with the map view +underneath. +<% if (iOS) { -%> +The user location annotation view, the attribution button, any buttons in callout views, and any items in the navigation bar are influenced by your application’s tint color, so choose a tint color that constrasts well with your map style. If you intend your style to be used in the dark, consider the impact -that the Night Shift mode on iOS may have on your style’s colors. +that Night Shift may have on your style’s colors. +<% } -%> ### Typography and graphics -Choose font and icon sizes appropriate to the device: iOS devices have smaller -screens than the typical browser window in which you would use Mapbox Studio, -and your user’s viewing distance may be shorter than on a desktop computer. Some -of your users may use the Dynamic Type and Accessibility Text features on iOS -and macOS to increase the size of all text on the device. You can use the +<% if (iOS) { -%> +Choose font and icon sizes appropriate to iOS devices. iPhones and iPads have +smaller screens than the typical browser window in which you would use Mapbox +Studio, especially when multitasking is enabled. Your user’s viewing distance +may be shorter than on a desktop computer. Some of your users may use the Larger +Dynamic Type and Accessibility Text features to increase the size of all text on +the device. You can use the [runtime styling API](#manipulating-the-style-at-runtime) to adjust your style’s font and icon sizes accordingly. +<% } -%> Design sprite images and choose font weights that look crisp on both standard-resolution displays and Retina displays. This SDK supports the same -resolutions as the operating system it runs on. On iOS, standard-resolution -displays are limited to older devices that your application may or may not -support, depending on its minimum deployment target. On macOS, -standard-resolution displays are often found on external monitors. +resolutions as <%- os %>. +<% if (iOS) { -%> +Standard-resolution displays are limited to older devices that your application +may or may not support, depending on its minimum deployment target. +<% } else { -%> +Standard-resolution displays are often found on external monitors. Even with +built-in screens, some of your users may use the Larger Text option in Display +Preferences, which is essentially standard resolution, to make text easier to +read. +<% } -%> + +Icon and text labels should be legible regardless of the map’s orientation. +<% if (iOS) { -%> +By default, this SDK makes it easy for your users to rotate or tilt the map +using multitouch gestures. +<% } else { -%> +By default, this SDK makes it easy for your users to rotate or tilt the map +using multitouch trackpad gestures or keyboard shortcuts. +<% } -%> +If you do not intend your design to accommodate rotation and tilting, disable +these gestures using the `MGLMapView.rotateEnabled` and +`MGLMapView.pitchEnabled` properties, respectively, or the corresponding +inspectables in Interface Builder. ### Interactivity -Pay attention to whether elements of your style appear to be interactive. An -icon with a shadow or shading effect may appear to be clickable on macOS. -Likewise, a text label may look like a tappable button on iOS merely due to -matching your application’s tint color or the default blue tint color. You can -actually make an icon or text label interactive by installing a gesture +Pay attention to whether elements of your style appear to be interactive. +<% if (iOS) { -%> +A text label may look like a tappable button merely due to matching your +application’s tint color or the default blue tint color. +<% } else { -%> +An icon with a shadow or shading effect may appear to be clickable. +<% } -%> +You can make an icon or text label interactive by installing a gesture recognizer and performing feature querying (e.g., `-[MGLMapView visibleFeaturesAtPoint:]`) to get details about the selected feature. +<% if (macOS) { -%> +You can install cursor or tooltip tracking rectangles to indicate interactive +features as an alternative to prominent hover effects. +<% } -%> +<% if (iOS) { -%> Make sure your users can easily distinguish any interactive elements from the surrounding map, such as pins, the user location annotation view, or a route -line. On iOS, avoid relying on hover effects to indicate interactive elements, -and leave enough room between interactive elements to accommodate imprecise -tapping gestures. +line. Avoid relying on hover effects to indicate interactive elements. Leave +enough room between interactive elements to accommodate imprecise tapping +gestures. +<% } else { -%> +Make sure your users can easily distinguish any interactive elements from the +surrounding map, such as pins or a route line. If your application supports +printing, consider using the +[runtime styling API](#manipulating-the-style-at-runtime) to optimize your style +for ink economy before printing the map view. +<% } -%> +<% if (iOS) { -%> +For more information about user interface design, consult Apple’s +[_iOS Human Interface Guidelines_](https://developer.apple.com/ios/human-interface-guidelines/). +<% } else { -%> For more information about user interface design, consult Apple’s -_Human Interface Guidelines_ document for -[iOS](https://developer.apple.com/ios/human-interface-guidelines/) or -[macOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). +[_macOS Human Interface Guidelines_](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). +<% } -%> ## Applying your style @@ -93,9 +144,9 @@ represented at runtime by an `MGLStyle` object, which provides access to various `MGLSource` and `MGLStyleLayer` objects that represent content sources and style layers, respectively. -The names of runtime styling classes and properties on iOS and macOS are -generally consistent with the style specification and Mapbox Studio’s Styles -editor. Any exceptions are listed in this document. +The names of runtime styling classes and properties on <%- os %> are generally +consistent with the style specification and Mapbox Studio’s Styles editor. Any +exceptions are listed in this document. To avoid conflicts with Objective-C keywords or Cocoa terminology, this SDK uses the following terms for concepts defined in the style specification: @@ -210,7 +261,7 @@ Pay close attention to the SDK documentation for the attribute you want to set. In style JSON | In Objective-C | In Swift --------------|-----------------------|--------- -Color | `NSColor` (macOS)
    `UIColor` (iOS) | `NSColor` (macOS)
    `UIColor` (iOS) +Color | `<%- cocoaPrefix %>Color` | `<%- cocoaPrefix %>Color` Enum | `NSValue` (see `NSValue(MGLAdditions)`) | `NSValue` (see `NSValue(MGLAdditions)`) String | `NSString` | `String` Boolean | `NSNumber.boolValue` | `NSNumber.boolValue` @@ -218,7 +269,7 @@ Number | `NSNumber.floatValue` | `NSNumber.floatValue` Array (`-dasharray`) | `NSArray` | `[NSNumber]` Array (`-font`) | `NSArray` | `[String]` Array (`-offset`, `-translate`) | `CGVector` | `CGVector` -Array (`-padding`) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) | `NSEdgeInsets` (macOS)
    `UIEdgeInsets` (iOS) +Array (`-padding`) | `<%- cocoaPrefix %>EdgeInsets` | `<%- cocoaPrefix %>EdgeInsets` ## Filtering sources diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js index 9d42972ab5..a656b48dd3 100644 --- a/platform/darwin/scripts/generate-style-code.js +++ b/platform/darwin/scripts/generate-style-code.js @@ -447,7 +447,13 @@ fs.writeFileSync(`platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm` paintProperties: _.flatten(allPaintProperties) })); -fs.writeFileSync(`platform/darwin/docs/guides/For Style Authors.md`, guideMD({ +fs.writeFileSync(`platform/ios/docs/guides/For Style Authors.md`, guideMD({ + os: 'iOS', + renamedProperties: allRenamedProperties, + types: allTypes, +})); +fs.writeFileSync(`platform/macos/docs/guides/For Style Authors.md`, guideMD({ + os: 'macOS', renamedProperties: allRenamedProperties, types: allTypes, })); diff --git a/platform/ios/docs/guides/For Style Authors.md b/platform/ios/docs/guides/For Style Authors.md new file mode 100644 index 0000000000..2e7ed6e4a7 --- /dev/null +++ b/platform/ios/docs/guides/For Style Authors.md @@ -0,0 +1,279 @@ + +# Information for Style Authors + +A _style_ defines a map view’s content and appearance. If you’ve authored a +style using +[Mapbox Studio’s Styles editor](https://www.mapbox.com/studio/styles/) or as +JSON in a text editor, you can use that style in this SDK and manipulate it +afterwards in code. This document provides information you can use to ensure a +seamless transition from Mapbox Studio to your application. + +## Designing for iOS + +When designing your style, consider the context in which your application shows +the style. There are a number of considerations specific to iOS that may +not be obvious when designing your style in Mapbox Studio on the Web. A map view +is essentially a graphical user interface element, so many of same issues in +user interface design also apply when designing a map style. + +### Color + +Ensure sufficient contrast in your application’s user interface when your map +style is present. Standard user interface elements such as toolbars, sidebars, +and sheets often overlap the map view with a translucent, blurred background, so +make sure the contents of these elements remain legible with the map view +underneath. +The user location annotation view, the attribution button, any buttons in +callout views, and any items in the navigation bar are influenced by your +application’s tint color, so choose a tint color that constrasts well with your +map style. If you intend your style to be used in the dark, consider the impact +that Night Shift may have on your style’s colors. + +### Typography and graphics + +Choose font and icon sizes appropriate to iOS devices. iPhones and iPads have +smaller screens than the typical browser window in which you would use Mapbox +Studio, especially when multitasking is enabled. Your user’s viewing distance +may be shorter than on a desktop computer. Some of your users may use the Larger +Dynamic Type and Accessibility Text features to increase the size of all text on +the device. You can use the +[runtime styling API](#manipulating-the-style-at-runtime) to adjust your style’s +font and icon sizes accordingly. + +Design sprite images and choose font weights that look crisp on both +standard-resolution displays and Retina displays. This SDK supports the same +resolutions as iOS. +Standard-resolution displays are limited to older devices that your application +may or may not support, depending on its minimum deployment target. + +Icon and text labels should be legible regardless of the map’s orientation. +By default, this SDK makes it easy for your users to rotate or tilt the map +using multitouch gestures. +If you do not intend your design to accommodate rotation and tilting, disable +these gestures using the `MGLMapView.rotateEnabled` and +`MGLMapView.pitchEnabled` properties, respectively, or the corresponding +inspectables in Interface Builder. + +### Interactivity + +Pay attention to whether elements of your style appear to be interactive. +A text label may look like a tappable button merely due to matching your +application’s tint color or the default blue tint color. +You can make an icon or text label interactive by installing a gesture +recognizer and performing feature querying (e.g., +`-[MGLMapView visibleFeaturesAtPoint:]`) to get details about the selected +feature. + +Make sure your users can easily distinguish any interactive elements from the +surrounding map, such as pins, the user location annotation view, or a route +line. Avoid relying on hover effects to indicate interactive elements. Leave +enough room between interactive elements to accommodate imprecise tapping +gestures. + +For more information about user interface design, consult Apple’s +[_iOS Human Interface Guidelines_](https://developer.apple.com/ios/human-interface-guidelines/). + +## Applying your style + +You set an `MGLMapView` object’s style either in code, by setting the +`MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style +URL” inspectable. The URL must point to a local or remote style JSON file. The +style JSON file format is defined by the +[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). This +SDK supports the functionality defined by version 8 of the specification unless +otherwise noted in the +[style specification documentation](https://www.mapbox.com/mapbox-gl-style-spec/). + +## Manipulating the style at runtime + +The _runtime styling API_ enables you to modify every aspect of a style +dynamically as a user interacts with your application. The style itself is +represented at runtime by an `MGLStyle` object, which provides access to various +`MGLSource` and `MGLStyleLayer` objects that represent content sources and style +layers, respectively. + +The names of runtime styling classes and properties on iOS are generally +consistent with the style specification and Mapbox Studio’s Styles editor. Any +exceptions are listed in this document. + +To avoid conflicts with Objective-C keywords or Cocoa terminology, this SDK uses +the following terms for concepts defined in the style specification: + +In the style specification | In the SDK +---------------------------|--------- +class | style class +filter | predicate +id | identifier +image | style image +layer | style layer +property | attribute +SDF icon | template image +source | content source + +## Specifying the map’s content + +Each source defined by a style JSON file is represented at runtime by a content +source object that you can use to initialize new style layers. The content +source object is a member of one of the following subclasses of `MGLSource`: + +In style JSON | In the SDK +--------------|----------- +`geojson` | `MGLShapeSource` +`raster` | `MGLRasterSource` +`vector` | `MGLVectorSource` + +`image` and `video` sources are not supported. + +### Tile sources + +Raster and vector sources may be defined in TileJSON configuration files. This +SDK supports the properties defined in the style specification, which are a +subset of the keys defined in version 2.1.0 of the +[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0) +specification. As an alternative to authoring a custom TileJSON file, you may +supply various tile source options when creating a raster or vector source. +These options are detailed in the `MGLTileSourceOption` documentation: + +In style JSON | In TileJSON | In the SDK +--------------|---------------|----------- +`url` | — | `configurationURL` parameter in `-[MGLTileSource initWithIdentifier:configurationURL:]` +`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]` +`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel` +`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel` +`tileSize` | — | `MGLTileSourceOptionTileSize` +`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security) +`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem` + +### Shape sources + +Shape sources also accept various options. These options are detailed in the +`MGLShapeSourceOption` documentation: + +In style JSON | In the SDK +-----------------|----------- +`data` | `url` parameter in `-[MGLShapeSource initWithIdentifier:URL:options:]` +`maxzoom` | `MGLShapeSourceOptionMaximumZoomLevel` +`buffer` | `MGLShapeSourceOptionBuffer` +`tolerance` | `MGLShapeSourceOptionSimplificationTolerance` +`cluster` | `MGLShapeSourceOptionClustered` +`clusterRadius` | `MGLShapeSourceOptionClusterRadius` +`clusterMaxZoom` | `MGLShapeSourceOptionMaximumZoomLevelForClustering` + +To create a shape source from local GeoJSON data, first +[convert the GeoJSON data into a shape](working-with-geojson-data.html#converting-geojson-data-into-shape-objects), +then use the `-[MGLShapeSource initWithIdentifier:shape:options:]` method. + +## Configuring the map content’s appearance + +Each layer defined by the style JSON file is represented at runtime by a style +layer object, which you can use to refine the map’s appearance. The style layer +object is a member of one of the following subclasses of `MGLStyleLayer`: + +In style JSON | In the SDK +--------------|----------- +`fill` | `MGLFillStyleLayer` +`line` | `MGLLineStyleLayer` +`symbol` | `MGLSymbolStyleLayer` +`circle` | `MGLCircleStyleLayer` +`raster` | `MGLRasterStyleLayer` +`background` | `MGLBackgroundStyleLayer` + +You configure layout and paint attributes by setting properties on these style +layer objects. The property names generally correspond to the style JSON +properties, except for the use of camelCase instead of kebab-case. Properties +whose names differ from the style specification are listed below: + +### Fill style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`fill-antialias` | `MGLFillStyleLayer.fillAntialiased` | `MGLFillStyleLayer.isFillAntialiased` + +### Line style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`line-dasharray` | `MGLLineStyleLayer.lineDashPattern` | `MGLLineStyleLayer.lineDashPattern` + +### Symbol style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`icon-allow-overlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` +`icon-ignore-placement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` +`icon-image` | `MGLSymbolStyleLayer.iconImageName` | `MGLSymbolStyleLayer.iconImageName` +`icon-optional` | `MGLSymbolStyleLayer.iconOptional` | `MGLSymbolStyleLayer.isIconOptional` +`icon-rotate` | `MGLSymbolStyleLayer.iconRotation` | `MGLSymbolStyleLayer.iconRotation` +`icon-size` | `MGLSymbolStyleLayer.iconScale` | `MGLSymbolStyleLayer.iconScale` +`icon-keep-upright` | `MGLSymbolStyleLayer.keepsIconUpright` | `MGLSymbolStyleLayer.keepsIconUpright` +`text-keep-upright` | `MGLSymbolStyleLayer.keepsTextUpright` | `MGLSymbolStyleLayer.keepsTextUpright` +`text-max-angle` | `MGLSymbolStyleLayer.maximumTextAngle` | `MGLSymbolStyleLayer.maximumTextAngle` +`text-max-width` | `MGLSymbolStyleLayer.maximumTextWidth` | `MGLSymbolStyleLayer.maximumTextWidth` +`symbol-avoid-edges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` +`text-allow-overlap` | `MGLSymbolStyleLayer.textAllowsOverlap` | `MGLSymbolStyleLayer.textAllowsOverlap` +`text-ignore-placement` | `MGLSymbolStyleLayer.textIgnoresPlacement` | `MGLSymbolStyleLayer.textIgnoresPlacement` +`text-justify` | `MGLSymbolStyleLayer.textJustification` | `MGLSymbolStyleLayer.textJustification` +`text-optional` | `MGLSymbolStyleLayer.textOptional` | `MGLSymbolStyleLayer.isTextOptional` +`text-rotate` | `MGLSymbolStyleLayer.textRotation` | `MGLSymbolStyleLayer.textRotation` + +### Raster style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`raster-brightness-max` | `MGLRasterStyleLayer.maximumRasterBrightness` | `MGLRasterStyleLayer.maximumRasterBrightness` +`raster-brightness-min` | `MGLRasterStyleLayer.minimumRasterBrightness` | `MGLRasterStyleLayer.minimumRasterBrightness` +`raster-hue-rotate` | `MGLRasterStyleLayer.rasterHueRotation` | `MGLRasterStyleLayer.rasterHueRotation` + +## Setting attribute values + +Each property representing a layout or paint attribute is set to an +`MGLStyleValue` object, which is either an `MGLStyleConstantValue` object (for +constant values) or an `MGLStyleFunction` object (for zoom level functions). The +style value object is a container for the raw value or function parameters that +you want the attribute to be set to. + +In contrast to the JSON type that the style specification defines for each +layout or paint property, the style value object often contains a more specific +Foundation or Cocoa type. General rules for attribute types are listed below. +Pay close attention to the SDK documentation for the attribute you want to set. + +In style JSON | In Objective-C | In Swift +--------------|-----------------------|--------- +Color | `UIColor` | `UIColor` +Enum | `NSValue` (see `NSValue(MGLAdditions)`) | `NSValue` (see `NSValue(MGLAdditions)`) +String | `NSString` | `String` +Boolean | `NSNumber.boolValue` | `NSNumber.boolValue` +Number | `NSNumber.floatValue` | `NSNumber.floatValue` +Array (`-dasharray`) | `NSArray` | `[NSNumber]` +Array (`-font`) | `NSArray` | `[String]` +Array (`-offset`, `-translate`) | `CGVector` | `CGVector` +Array (`-padding`) | `UIEdgeInsets` | `UIEdgeInsets` + +## Filtering sources + +You can filter a shape or vector source by setting the +`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a +table of style JSON operators and the corresponding operators used in the +predicate format string: + +In style JSON | In the format string +--------------------------|--------------------- +`["has", key]` | `key != nil` +`["!has", key]` | `key == nil` +`["==", key, value]` | `key == value` +`["!=", key, value]` | `key != value` +`[">", key, value]` | `key > value` +`[">=", key, value]` | `key >= value` +`["<", key, value]` | `key < value` +`["<=", key, value]` | `key <= value` +`["in", key, v0, …, vn]` | `key IN {v0, …, vn}` +`["!in", key, v0, …, vn]` | `NOT key IN {v0, …, vn}` +`["all", f0, …, fn]` | `p0 AND … AND pn` +`["any", f0, …, fn]` | `p0 OR … OR pn` +`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)` + +See the `MGLVectorStyleLayer.predicate` documentation for a full description of +the supported operators and operand types. diff --git a/platform/macos/docs/guides/For Style Authors.md b/platform/macos/docs/guides/For Style Authors.md new file mode 100644 index 0000000000..ceefbcb6ec --- /dev/null +++ b/platform/macos/docs/guides/For Style Authors.md @@ -0,0 +1,269 @@ + +# Information for Style Authors + +A _style_ defines a map view’s content and appearance. If you’ve authored a +style using +[Mapbox Studio’s Styles editor](https://www.mapbox.com/studio/styles/) or as +JSON in a text editor, you can use that style in this SDK and manipulate it +afterwards in code. This document provides information you can use to ensure a +seamless transition from Mapbox Studio to your application. + +## Designing for macOS + +When designing your style, consider the context in which your application shows +the style. There are a number of considerations specific to macOS that may +not be obvious when designing your style in Mapbox Studio on the Web. A map view +is essentially a graphical user interface element, so many of same issues in +user interface design also apply when designing a map style. + +### Color + +Ensure sufficient contrast in your application’s user interface when your map +style is present. Standard user interface elements such as toolbars, sidebars, +and sheets often overlap the map view with a translucent, blurred background, so +make sure the contents of these elements remain legible with the map view +underneath. + +### Typography and graphics + + +Design sprite images and choose font weights that look crisp on both +standard-resolution displays and Retina displays. This SDK supports the same +resolutions as macOS. +Standard-resolution displays are often found on external monitors. Even with +built-in screens, some of your users may use the Larger Text option in Display +Preferences, which is essentially standard resolution, to make text easier to +read. + +Icon and text labels should be legible regardless of the map’s orientation. +By default, this SDK makes it easy for your users to rotate or tilt the map +using multitouch trackpad gestures or keyboard shortcuts. +If you do not intend your design to accommodate rotation and tilting, disable +these gestures using the `MGLMapView.rotateEnabled` and +`MGLMapView.pitchEnabled` properties, respectively, or the corresponding +inspectables in Interface Builder. + +### Interactivity + +Pay attention to whether elements of your style appear to be interactive. +An icon with a shadow or shading effect may appear to be clickable. +You can make an icon or text label interactive by installing a gesture +recognizer and performing feature querying (e.g., +`-[MGLMapView visibleFeaturesAtPoint:]`) to get details about the selected +feature. +You can install cursor or tooltip tracking rectangles to indicate interactive +features as an alternative to prominent hover effects. + +Make sure your users can easily distinguish any interactive elements from the +surrounding map, such as pins or a route line. If your application supports +printing, consider using the +[runtime styling API](#manipulating-the-style-at-runtime) to optimize your style +for ink economy before printing the map view. + +For more information about user interface design, consult Apple’s +[_macOS Human Interface Guidelines_](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/OSXHIGuidelines/). + +## Applying your style + +You set an `MGLMapView` object’s style either in code, by setting the +`MGLMapView.styleURL` property, or in Interface Builder, by setting the “Style +URL” inspectable. The URL must point to a local or remote style JSON file. The +style JSON file format is defined by the +[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). This +SDK supports the functionality defined by version 8 of the specification unless +otherwise noted in the +[style specification documentation](https://www.mapbox.com/mapbox-gl-style-spec/). + +## Manipulating the style at runtime + +The _runtime styling API_ enables you to modify every aspect of a style +dynamically as a user interacts with your application. The style itself is +represented at runtime by an `MGLStyle` object, which provides access to various +`MGLSource` and `MGLStyleLayer` objects that represent content sources and style +layers, respectively. + +The names of runtime styling classes and properties on macOS are generally +consistent with the style specification and Mapbox Studio’s Styles editor. Any +exceptions are listed in this document. + +To avoid conflicts with Objective-C keywords or Cocoa terminology, this SDK uses +the following terms for concepts defined in the style specification: + +In the style specification | In the SDK +---------------------------|--------- +class | style class +filter | predicate +id | identifier +image | style image +layer | style layer +property | attribute +SDF icon | template image +source | content source + +## Specifying the map’s content + +Each source defined by a style JSON file is represented at runtime by a content +source object that you can use to initialize new style layers. The content +source object is a member of one of the following subclasses of `MGLSource`: + +In style JSON | In the SDK +--------------|----------- +`geojson` | `MGLShapeSource` +`raster` | `MGLRasterSource` +`vector` | `MGLVectorSource` + +`image` and `video` sources are not supported. + +### Tile sources + +Raster and vector sources may be defined in TileJSON configuration files. This +SDK supports the properties defined in the style specification, which are a +subset of the keys defined in version 2.1.0 of the +[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0) +specification. As an alternative to authoring a custom TileJSON file, you may +supply various tile source options when creating a raster or vector source. +These options are detailed in the `MGLTileSourceOption` documentation: + +In style JSON | In TileJSON | In the SDK +--------------|---------------|----------- +`url` | — | `configurationURL` parameter in `-[MGLTileSource initWithIdentifier:configurationURL:]` +`tiles` | `tiles` | `tileURLTemplates` parameter in `-[MGLTileSource initWithIdentifier:tileURLTemplates:options:]` +`minzoom` | `minzoom` | `MGLTileSourceOptionMinimumZoomLevel` +`maxzoom` | `maxzoom` | `MGLTileSourceOptionMaximumZoomLevel` +`tileSize` | — | `MGLTileSourceOptionTileSize` +`attribution` | `attribution` | `MGLTileSourceOptionAttributionHTMLString` (but consider specifying `MGLTileSourceOptionAttributionInfos` instead for improved security) +`scheme` | `scheme` | `MGLTileSourceOptionTileCoordinateSystem` + +### Shape sources + +Shape sources also accept various options. These options are detailed in the +`MGLShapeSourceOption` documentation: + +In style JSON | In the SDK +-----------------|----------- +`data` | `url` parameter in `-[MGLShapeSource initWithIdentifier:URL:options:]` +`maxzoom` | `MGLShapeSourceOptionMaximumZoomLevel` +`buffer` | `MGLShapeSourceOptionBuffer` +`tolerance` | `MGLShapeSourceOptionSimplificationTolerance` +`cluster` | `MGLShapeSourceOptionClustered` +`clusterRadius` | `MGLShapeSourceOptionClusterRadius` +`clusterMaxZoom` | `MGLShapeSourceOptionMaximumZoomLevelForClustering` + +To create a shape source from local GeoJSON data, first +[convert the GeoJSON data into a shape](working-with-geojson-data.html#converting-geojson-data-into-shape-objects), +then use the `-[MGLShapeSource initWithIdentifier:shape:options:]` method. + +## Configuring the map content’s appearance + +Each layer defined by the style JSON file is represented at runtime by a style +layer object, which you can use to refine the map’s appearance. The style layer +object is a member of one of the following subclasses of `MGLStyleLayer`: + +In style JSON | In the SDK +--------------|----------- +`fill` | `MGLFillStyleLayer` +`line` | `MGLLineStyleLayer` +`symbol` | `MGLSymbolStyleLayer` +`circle` | `MGLCircleStyleLayer` +`raster` | `MGLRasterStyleLayer` +`background` | `MGLBackgroundStyleLayer` + +You configure layout and paint attributes by setting properties on these style +layer objects. The property names generally correspond to the style JSON +properties, except for the use of camelCase instead of kebab-case. Properties +whose names differ from the style specification are listed below: + +### Fill style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`fill-antialias` | `MGLFillStyleLayer.fillAntialiased` | `MGLFillStyleLayer.isFillAntialiased` + +### Line style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`line-dasharray` | `MGLLineStyleLayer.lineDashPattern` | `MGLLineStyleLayer.lineDashPattern` + +### Symbol style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`icon-allow-overlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` | `MGLSymbolStyleLayer.iconAllowsOverlap` +`icon-ignore-placement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` | `MGLSymbolStyleLayer.iconIgnoresPlacement` +`icon-image` | `MGLSymbolStyleLayer.iconImageName` | `MGLSymbolStyleLayer.iconImageName` +`icon-optional` | `MGLSymbolStyleLayer.iconOptional` | `MGLSymbolStyleLayer.isIconOptional` +`icon-rotate` | `MGLSymbolStyleLayer.iconRotation` | `MGLSymbolStyleLayer.iconRotation` +`icon-size` | `MGLSymbolStyleLayer.iconScale` | `MGLSymbolStyleLayer.iconScale` +`icon-keep-upright` | `MGLSymbolStyleLayer.keepsIconUpright` | `MGLSymbolStyleLayer.keepsIconUpright` +`text-keep-upright` | `MGLSymbolStyleLayer.keepsTextUpright` | `MGLSymbolStyleLayer.keepsTextUpright` +`text-max-angle` | `MGLSymbolStyleLayer.maximumTextAngle` | `MGLSymbolStyleLayer.maximumTextAngle` +`text-max-width` | `MGLSymbolStyleLayer.maximumTextWidth` | `MGLSymbolStyleLayer.maximumTextWidth` +`symbol-avoid-edges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` | `MGLSymbolStyleLayer.symbolAvoidsEdges` +`text-allow-overlap` | `MGLSymbolStyleLayer.textAllowsOverlap` | `MGLSymbolStyleLayer.textAllowsOverlap` +`text-ignore-placement` | `MGLSymbolStyleLayer.textIgnoresPlacement` | `MGLSymbolStyleLayer.textIgnoresPlacement` +`text-justify` | `MGLSymbolStyleLayer.textJustification` | `MGLSymbolStyleLayer.textJustification` +`text-optional` | `MGLSymbolStyleLayer.textOptional` | `MGLSymbolStyleLayer.isTextOptional` +`text-rotate` | `MGLSymbolStyleLayer.textRotation` | `MGLSymbolStyleLayer.textRotation` + +### Raster style layers + +In style JSON | In Objective-C | In Swift +--------------|----------------|--------- +`raster-brightness-max` | `MGLRasterStyleLayer.maximumRasterBrightness` | `MGLRasterStyleLayer.maximumRasterBrightness` +`raster-brightness-min` | `MGLRasterStyleLayer.minimumRasterBrightness` | `MGLRasterStyleLayer.minimumRasterBrightness` +`raster-hue-rotate` | `MGLRasterStyleLayer.rasterHueRotation` | `MGLRasterStyleLayer.rasterHueRotation` + +## Setting attribute values + +Each property representing a layout or paint attribute is set to an +`MGLStyleValue` object, which is either an `MGLStyleConstantValue` object (for +constant values) or an `MGLStyleFunction` object (for zoom level functions). The +style value object is a container for the raw value or function parameters that +you want the attribute to be set to. + +In contrast to the JSON type that the style specification defines for each +layout or paint property, the style value object often contains a more specific +Foundation or Cocoa type. General rules for attribute types are listed below. +Pay close attention to the SDK documentation for the attribute you want to set. + +In style JSON | In Objective-C | In Swift +--------------|-----------------------|--------- +Color | `NSColor` | `NSColor` +Enum | `NSValue` (see `NSValue(MGLAdditions)`) | `NSValue` (see `NSValue(MGLAdditions)`) +String | `NSString` | `String` +Boolean | `NSNumber.boolValue` | `NSNumber.boolValue` +Number | `NSNumber.floatValue` | `NSNumber.floatValue` +Array (`-dasharray`) | `NSArray` | `[NSNumber]` +Array (`-font`) | `NSArray` | `[String]` +Array (`-offset`, `-translate`) | `CGVector` | `CGVector` +Array (`-padding`) | `NSEdgeInsets` | `NSEdgeInsets` + +## Filtering sources + +You can filter a shape or vector source by setting the +`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a +table of style JSON operators and the corresponding operators used in the +predicate format string: + +In style JSON | In the format string +--------------------------|--------------------- +`["has", key]` | `key != nil` +`["!has", key]` | `key == nil` +`["==", key, value]` | `key == value` +`["!=", key, value]` | `key != value` +`[">", key, value]` | `key > value` +`[">=", key, value]` | `key >= value` +`["<", key, value]` | `key < value` +`["<=", key, value]` | `key <= value` +`["in", key, v0, …, vn]` | `key IN {v0, …, vn}` +`["!in", key, v0, …, vn]` | `NOT key IN {v0, …, vn}` +`["all", f0, …, fn]` | `p0 AND … AND pn` +`["any", f0, …, fn]` | `p0 OR … OR pn` +`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)` + +See the `MGLVectorStyleLayer.predicate` documentation for a full description of +the supported operators and operand types. -- cgit v1.2.1 From ef9954b566fbd666edf2237ee24097969f438879 Mon Sep 17 00:00:00 2001 From: Eric Wolfe Date: Wed, 4 Jan 2017 11:04:30 -0800 Subject: [ios] Runtime styling guide fixes --- platform/ios/docs/guides/Runtime Styling.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'platform') diff --git a/platform/ios/docs/guides/Runtime Styling.md b/platform/ios/docs/guides/Runtime Styling.md index afc2ccae87..deace0d728 100644 --- a/platform/ios/docs/guides/Runtime Styling.md +++ b/platform/ios/docs/guides/Runtime Styling.md @@ -1,6 +1,6 @@ # Runtime Styling -Mapbox's runtime styling features allow you direct control over every layer in your maps with code. It's now possible create dynamic maps and visualizations that aren't possible with other mobile maps SDKs. +Mapbox's runtime styling features allow you direct control over every layer in your maps with code. It's now possible to create dynamic maps and visualizations that aren't possible with other mobile maps SDKs. Runtime styling expands upon the design power of [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) and exposes all of the same properties and attributes directly to mobile developers in our SDK. @@ -44,10 +44,6 @@ The Mapbox SDK gives you access to all of the same tools we use to render our de Draw custom shapes on the map the same way you would a custom `UIView` or `CALayer`. These shapes keep their geographic scale and are perfect for visualizing everything from indoor floor plans to metro systems to hurricane tracks. - - - - ## Resources * [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) -- cgit v1.2.1 From d2efbc99159a6503e483b41e5adf43656c6413d3 Mon Sep 17 00:00:00 2001 From: Eric Wolfe Date: Wed, 4 Jan 2017 11:26:00 -0800 Subject: [ios, macos] Move Info.plist keys down in jazzy sidebar --- platform/ios/jazzy.yml | 2 +- platform/macos/jazzy.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'platform') diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml index 1ba341bd17..82fe3e8115 100644 --- a/platform/ios/jazzy.yml +++ b/platform/ios/jazzy.yml @@ -20,9 +20,9 @@ custom_categories: - Adding Points to a Map - Runtime Styling - Working with Mapbox Studio - - Info.plist Keys - Working with GeoJSON Data - For Style Authors + - Info.plist Keys - name: Maps children: - MGLAccountManager diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml index 6f88c01bc6..4b5bdf2d42 100644 --- a/platform/macos/jazzy.yml +++ b/platform/macos/jazzy.yml @@ -16,9 +16,9 @@ framework_root: ../darwin/src custom_categories: - name: Guides children: - - Info.plist Keys - Working with GeoJSON Data - For Style Authors + - Info.plist Keys - name: Maps children: - MGLAccountManager -- cgit v1.2.1 From 2382f199c11ae7c864fc41ac83aadc83b560ca10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 4 Jan 2017 18:52:22 -0800 Subject: [ios] Link guides to each other --- platform/darwin/docs/guides/For Style Authors.md.ejs | 4 ++++ platform/ios/docs/guides/For Style Authors.md | 2 ++ platform/ios/docs/guides/Runtime Styling.md | 2 ++ platform/ios/docs/guides/Working with Mapbox Studio.md | 15 +++++++-------- 4 files changed, 15 insertions(+), 8 deletions(-) (limited to 'platform') diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index 0bd9bbecd9..cbe38ff6ba 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -143,6 +143,10 @@ dynamically as a user interacts with your application. The style itself is represented at runtime by an `MGLStyle` object, which provides access to various `MGLSource` and `MGLStyleLayer` objects that represent content sources and style layers, respectively. +<% if (iOS) { -%> +For more information about the capabilities exposed by the runtime styling API, +see “[Runtime Styling](runtime-styling.html)”. +<% } -%> The names of runtime styling classes and properties on <%- os %> are generally consistent with the style specification and Mapbox Studio’s Styles editor. Any diff --git a/platform/ios/docs/guides/For Style Authors.md b/platform/ios/docs/guides/For Style Authors.md index 2e7ed6e4a7..96a0661af6 100644 --- a/platform/ios/docs/guides/For Style Authors.md +++ b/platform/ios/docs/guides/For Style Authors.md @@ -94,6 +94,8 @@ dynamically as a user interacts with your application. The style itself is represented at runtime by an `MGLStyle` object, which provides access to various `MGLSource` and `MGLStyleLayer` objects that represent content sources and style layers, respectively. +For more information about the capabilities exposed by the runtime styling API, +see “[Runtime Styling](runtime-styling.html)”. The names of runtime styling classes and properties on iOS are generally consistent with the style specification and Mapbox Studio’s Styles editor. Any diff --git a/platform/ios/docs/guides/Runtime Styling.md b/platform/ios/docs/guides/Runtime Styling.md index deace0d728..6a4718980d 100644 --- a/platform/ios/docs/guides/Runtime Styling.md +++ b/platform/ios/docs/guides/Runtime Styling.md @@ -46,6 +46,8 @@ Draw custom shapes on the map the same way you would a custom `UIView` or `CALay ## Resources +* [Information for style authors](for-style-authors.html) +* [Mapbox Streets source reference](https://www.mapbox.com/vector-tiles/mapbox-streets-v7/) * [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) * [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) * [iOS code examples](https://www.mapbox.com/ios-sdk/examples/) diff --git a/platform/ios/docs/guides/Working with Mapbox Studio.md b/platform/ios/docs/guides/Working with Mapbox Studio.md index 97aa614c41..2360bf6421 100644 --- a/platform/ios/docs/guides/Working with Mapbox Studio.md +++ b/platform/ios/docs/guides/Working with Mapbox Studio.md @@ -1,6 +1,6 @@ # Working with Mapbox Studio -[Mapbox Studio](http://mapbox.com/studio) is Mapbox's tool for creating custom map styles. It also serves as an excellent tool for rapidly prototyping dynamic maps and runtime styling interactions for iOS. +[Mapbox Studio’s Styles editor](http://mapbox.com/studio) is Mapbox's tool for creating custom map styles. It also serves as an excellent tool for rapidly prototyping dynamic maps and [runtime styling](runtime-styling.html) interactions for iOS. ## Creating a base style @@ -38,7 +38,7 @@ Next, add data properties you'd like to use to drive your style. Consider catego * Text along a line: add line with a text property * Text at specific points on a line or polygon: in addition to the line, create points at the specific points you'd like with text properties * If you want circles where scale doesn't matter relative to the geography (e.g. always 20 pixels), you can add as a point and style with a circle layer or a symbol -* If you want circles or arcs where the scale matters (e.g. 10 mile radius), you'll need to approximately freehand a polygon, and you can create more precisely later in code. +* If you want circles or arcs where the scale matters (e.g. 10 mile radius), you'll need to approximately freehand a polygon that you can create more precisely later in code. When you're done, save your dataset and export as a tileset. When that's complete, add your tileset to your style. @@ -74,18 +74,18 @@ Once you're happy with the styles you've created, it's time to [get setup with M To implement your prototypes with runtime styling: -1. Implement `MGLMapViewDelegate` `-mapView:didFinishLoadingStyle:` -2. Add your real data as a source +1. Implement `-[MGLMapViewDelegate mapView:didFinishLoadingStyle:]`. +2. Add your real data as a source: * This can be done using vector data from tileset editor ([example](https://www.mapbox.com/ios-sdk/examples/runtime-circle-styles)), custom vector tiles, added as GeoJSON ([example](https://www.mapbox.com/ios-sdk/examples/runtime-add-line), or added manually through the app via `MGLShapeSource` ([example](https://www.mapbox.com/ios-sdk/examples/runtime-multiple-annotations)) -3. For each layer you've prototyped in studio, add it's corresponding `MGLStyleLayer` subclass: `MGLSymbolStyleLayer`, `MGLLineStyleLayer`, `MGLFillStyleLayer`, or `MGLCircleStyleLayer`. +3. For each layer you've prototyped in Studio, add its corresponding `MGLStyleLayer` subclass. See [“Configuring the map content’s appearance”](for-style-authors.html#configuring-the-map-content-s-appearance) for the available style layer classes. **Translating style attributes from Studio** -For each property you've edited in Studio, you can hover over the property name to find it's corresponding property in the iOS SDK. They're generally the camelCased version of the Property ID. +For each property you've edited in Studio, you can hover over the property name to find the corresponding property in the iOS SDK. It’ll generally be the camelCased version of the Property ID, but see [“Configuring the map content’s appearance”](for-style-authors.html#configuring-the-map-content-s-appearance) for a table of properties that differ between Mapbox Studio and the iOS SDK. ![property values](img/studio-workflow/property-values.png) **Translating stop functions** -It's possible to use stop functions in Mapbox Studio to transition the style of a layer by it's zoom level (e.g. a line that gets wider as you zoom in). These can be translated in the mobile SDKs using `+[MGLSyleValue valueWithInterpolationBase:stops:]`. The rate of change between stops in studio is represented by `interpolationBase`. +It's possible to use stop functions in Mapbox Studio to transition the style of a layer by its zoom level (e.g. a line that gets wider as you zoom in). These can be translated in the mobile SDKs using `+[MGLSyleValue valueWithInterpolationBase:stops:]`. The rate of change between stops in Studio is represented by `interpolationBase`. ![Stop functions](img/studio-workflow/stop-functions.png) @@ -94,4 +94,3 @@ It's possible to use stop functions in Mapbox Studio to transition the style of * [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/) * [Mapbox Studio](https://www.mapbox.com/mapbox-studio/) * [iOS code examples](https://www.mapbox.com/ios-sdk/examples/) - -- cgit v1.2.1 From 188a61af55d54a58740b77d572b442fc298bdb0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguy=E1=BB=85n?= Date: Wed, 4 Jan 2017 18:10:52 -0800 Subject: [macos] Fixed changelog parsing Updated changelog parsing code to handle subheadings within release notes. --- platform/macos/scripts/document.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'platform') diff --git a/platform/macos/scripts/document.sh b/platform/macos/scripts/document.sh index 22b7685c7e..1ca65540ed 100755 --- a/platform/macos/scripts/document.sh +++ b/platform/macos/scripts/document.sh @@ -25,7 +25,7 @@ README=/tmp/mbgl/README.md cp platform/macos/docs/doc-README.md "${README}" # http://stackoverflow.com/a/4858011/4585461 echo "## Changes in version ${RELEASE_VERSION}" >> "${README}" -sed -n -e '/^## /{' -e ':a' -e 'n' -e '/^##/q' -e 'p' -e 'ba' -e '}' platform/macos/CHANGELOG.md >> "${README}" +sed -n -e '/^## /{' -e ':a' -e 'n' -e '/^## /q' -e 'p' -e 'ba' -e '}' platform/macos/CHANGELOG.md >> "${README}" rm -rf ${OUTPUT} mkdir -p ${OUTPUT} -- cgit v1.2.1 From b6f7d03e5d4cb632dd3c59e3c6451e33fadca945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 23 Dec 2016 15:01:00 -0800 Subject: [ios, macos] Sources, layers properties are immutable If you need a mutable array of layers, use -mutableArrayValueForKey:. --- platform/darwin/src/MGLStyle.h | 4 ++-- platform/darwin/src/MGLStyle.mm | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index cc87d7defd..58bc57b4fa 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -189,7 +189,7 @@ static const NSInteger MGLStyleDefaultVersion = 9; /** A set containing the style’s sources. */ -@property (nonatomic, strong) NS_MUTABLE_SET_OF(MGLSource *) *sources; +@property (nonatomic, strong) NS_SET_OF(MGLSource *) *sources; /** Returns a source with the given identifier in the current style. @@ -240,7 +240,7 @@ static const NSInteger MGLStyleDefaultVersion = 9; The layers included in the style, arranged according to their back-to-front ordering on the screen. */ -@property (nonatomic, strong) NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *layers; +@property (nonatomic, strong) NS_ARRAY_OF(MGLStyleLayer *) *layers; /** Returns a style layer with the given identifier in the current style. diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 10f4aabe19..959ba4e363 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -127,7 +127,7 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Sources -- (NS_MUTABLE_SET_OF(MGLSource *) *)sources { +- (NS_SET_OF(MGLSource *) *)sources { auto rawSources = self.mapView.mbglMap->getSources(); NSMutableSet *sources = [NSMutableSet setWithCapacity:rawSources.size()]; for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { @@ -137,7 +137,7 @@ static NSURL *MGLStyleURL_emerald; return sources; } -- (void)setSources:(NS_MUTABLE_SET_OF(MGLSource *) *)sources { +- (void)setSources:(NS_SET_OF(MGLSource *) *)sources { for (MGLSource *source in self.sources) { [self removeSource:source]; } @@ -222,7 +222,7 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Style layers -- (NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers +- (NS_ARRAY_OF(MGLStyleLayer *) *)layers { auto layers = self.mapView.mbglMap->getLayers(); NSMutableArray *styleLayers = [NSMutableArray arrayWithCapacity:layers.size()]; @@ -233,7 +233,7 @@ static NSURL *MGLStyleURL_emerald; return styleLayers; } -- (void)setLayers:(NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers { +- (void)setLayers:(NS_ARRAY_OF(MGLStyleLayer *) *)layers { for (MGLStyleLayer *layer in self.layers) { [self removeLayer:layer]; } -- cgit v1.2.1 From 4700c72e1501aca9509d9e051b1afc2d2112597e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Fri, 23 Dec 2016 15:14:54 -0800 Subject: [ios, macos] Relaxed sources, layers type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refined the types of MGLStyle’s sources and layers types so that Objective-C code can easily send messages intended for subclasses of MGLSource or MGLStyleLayer that are contained in one of these containers. --- platform/darwin/src/MGLStyle.h | 4 ++-- platform/darwin/src/MGLStyle.mm | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'platform') diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index 58bc57b4fa..ea7f8ed5cb 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -189,7 +189,7 @@ static const NSInteger MGLStyleDefaultVersion = 9; /** A set containing the style’s sources. */ -@property (nonatomic, strong) NS_SET_OF(MGLSource *) *sources; +@property (nonatomic, strong) NS_SET_OF(__kindof MGLSource *) *sources; /** Returns a source with the given identifier in the current style. @@ -240,7 +240,7 @@ static const NSInteger MGLStyleDefaultVersion = 9; The layers included in the style, arranged according to their back-to-front ordering on the screen. */ -@property (nonatomic, strong) NS_ARRAY_OF(MGLStyleLayer *) *layers; +@property (nonatomic, strong) NS_ARRAY_OF(__kindof MGLStyleLayer *) *layers; /** Returns a style layer with the given identifier in the current style. diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 959ba4e363..fcfa762972 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -127,9 +127,9 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Sources -- (NS_SET_OF(MGLSource *) *)sources { +- (NS_SET_OF(__kindof MGLSource *) *)sources { auto rawSources = self.mapView.mbglMap->getSources(); - NSMutableSet *sources = [NSMutableSet setWithCapacity:rawSources.size()]; + NS_MUTABLE_SET_OF(__kindof MGLSource *) *sources = [NSMutableSet setWithCapacity:rawSources.size()]; for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { MGLSource *source = [self sourceFromMBGLSource:*rawSource]; [sources addObject:source]; @@ -137,7 +137,7 @@ static NSURL *MGLStyleURL_emerald; return sources; } -- (void)setSources:(NS_SET_OF(MGLSource *) *)sources { +- (void)setSources:(NS_SET_OF(__kindof MGLSource *) *)sources { for (MGLSource *source in self.sources) { [self removeSource:source]; } @@ -222,10 +222,10 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Style layers -- (NS_ARRAY_OF(MGLStyleLayer *) *)layers +- (NS_ARRAY_OF(__kindof MGLStyleLayer *) *)layers { auto layers = self.mapView.mbglMap->getLayers(); - NSMutableArray *styleLayers = [NSMutableArray arrayWithCapacity:layers.size()]; + NS_MUTABLE_ARRAY_OF(__kindof MGLStyleLayer *) *styleLayers = [NSMutableArray arrayWithCapacity:layers.size()]; for (auto layer : layers) { MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:layer]; [styleLayers addObject:styleLayer]; @@ -233,7 +233,7 @@ static NSURL *MGLStyleURL_emerald; return styleLayers; } -- (void)setLayers:(NS_ARRAY_OF(MGLStyleLayer *) *)layers { +- (void)setLayers:(NS_ARRAY_OF(__kindof MGLStyleLayer *) *)layers { for (MGLStyleLayer *layer in self.layers) { [self removeLayer:layer]; } -- cgit v1.2.1 From 428c0fdf70d08dfe433058a66a61bf9c4fb93d9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Thu, 29 Dec 2016 23:24:22 -0800 Subject: [macos] Arrange layers top to bottom in sidebar Implemented a reversedLayers property on MGLStyle based on the layers property. --- platform/macos/app/Base.lproj/MapDocument.xib | 3 +- platform/macos/app/MGLStyle+MBXAdditions.h | 7 +++++ platform/macos/app/MGLStyle+MBXAdditions.m | 42 ++++++++++++++++++++++++++ platform/macos/app/MapDocument.m | 7 +++-- platform/macos/macos.xcodeproj/project.pbxproj | 6 ++++ 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 platform/macos/app/MGLStyle+MBXAdditions.h create mode 100644 platform/macos/app/MGLStyle+MBXAdditions.m (limited to 'platform') diff --git a/platform/macos/app/Base.lproj/MapDocument.xib b/platform/macos/app/Base.lproj/MapDocument.xib index e147ba83d0..4ba8f0a3ad 100644 --- a/platform/macos/app/Base.lproj/MapDocument.xib +++ b/platform/macos/app/Base.lproj/MapDocument.xib @@ -27,6 +27,7 @@ layers name + reversedLayers @@ -38,7 +39,7 @@ visible - + diff --git a/platform/macos/app/MGLStyle+MBXAdditions.h b/platform/macos/app/MGLStyle+MBXAdditions.h new file mode 100644 index 0000000000..dcaf42af28 --- /dev/null +++ b/platform/macos/app/MGLStyle+MBXAdditions.h @@ -0,0 +1,7 @@ +#import + +@interface MGLStyle (MBXAdditions) + +@property (nonatomic, strong) NS_ARRAY_OF(__kindof MGLStyleLayer *) *reversedLayers; + +@end diff --git a/platform/macos/app/MGLStyle+MBXAdditions.m b/platform/macos/app/MGLStyle+MBXAdditions.m new file mode 100644 index 0000000000..be571d8b30 --- /dev/null +++ b/platform/macos/app/MGLStyle+MBXAdditions.m @@ -0,0 +1,42 @@ +#import "MGLStyle+MBXAdditions.h" + +@implementation MGLStyle (MBXAdditions) + ++ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingReversedLayers { + return [NSSet setWithObject:@"layers"]; +} + +- (NS_ARRAY_OF(__kindof MGLStyleLayer *) *)reversedLayers { + return self.layers.reverseObjectEnumerator.allObjects; +} + +- (void)setReversedLayers:(NS_ARRAY_OF(__kindof MGLStyleLayer *) *)reversedLayers { + self.layers = reversedLayers.reverseObjectEnumerator.allObjects; +} + +- (NSUInteger)countOfReversedLayers { + return self.layers.count; +} + +- (id)objectInReversedLayersAtIndex:(NSUInteger)index { + NSArray *layers = self.layers; + return layers[layers.count - 1 - index]; +} + +- (void)getReversedLayers:(__kindof MGLStyleLayer **)buffer range:(NSRange)inRange { + NSArray *layers = self.layers; + for (NSUInteger i = inRange.location; i < NSMaxRange(inRange); i++) { + MGLStyleLayer *styleLayer = layers[layers.count - 1 - i]; + buffer[i] = styleLayer; + } +} + +- (void)insertObject:(__kindof MGLStyleLayer *)object inReversedLayersAtIndex:(NSUInteger)index { + [self insertLayer:object atIndex:self.layers.count - index]; +} + +- (void)removeObjectFromReversedLayersAtIndex:(NSUInteger)index { + [self removeLayer:[self objectInReversedLayersAtIndex:index]]; +} + +@end diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m index 705ebb8a45..f00f773bf9 100644 --- a/platform/macos/app/MapDocument.m +++ b/platform/macos/app/MapDocument.m @@ -4,6 +4,7 @@ #import "LimeGreenStyleLayer.h" #import "DroppedPinAnnotation.h" +#import "MGLStyle+MBXAdditions.h" #import "MGLVectorSource+MBXAdditions.h" #import @@ -256,7 +257,7 @@ NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id Date: Mon, 2 Jan 2017 15:54:17 -0800 Subject: [ios, macos] Split NSValue+MGLStyleEnumAttributeAdditions category per style layer type Also renamed the file to have a slightly more wieldy name. --- .../darwin/docs/guides/For Style Authors.md.ejs | 6 +- platform/darwin/scripts/generate-style-code.js | 62 +++-- platform/darwin/src/MGLStyleValue_Private.h | 1 - .../src/NSValue+MGLStyleEnumAttributeAdditions.h | 232 ------------------ .../NSValue+MGLStyleEnumAttributeAdditions.h.ejs | 66 ------ .../src/NSValue+MGLStyleEnumAttributeAdditions.mm | 169 ------------- .../NSValue+MGLStyleEnumAttributeAdditions.mm.ejs | 46 ---- .../darwin/src/NSValue+MGLStyleLayerAdditions.h | 261 +++++++++++++++++++++ .../src/NSValue+MGLStyleLayerAdditions.h.ejs | 44 ++++ .../darwin/src/NSValue+MGLStyleLayerAdditions.mm | 181 ++++++++++++++ .../src/NSValue+MGLStyleLayerAdditions.mm.ejs | 28 +++ platform/ios/docs/guides/For Style Authors.md | 22 +- platform/ios/ios.xcodeproj/project.pbxproj | 32 +-- platform/ios/src/Mapbox.h | 2 +- platform/macos/docs/guides/For Style Authors.md | 22 +- platform/macos/macos.xcodeproj/project.pbxproj | 24 +- platform/macos/src/Mapbox.h | 2 +- 17 files changed, 598 insertions(+), 602 deletions(-) delete mode 100644 platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h delete mode 100644 platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs delete mode 100644 platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm delete mode 100644 platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs create mode 100644 platform/darwin/src/NSValue+MGLStyleLayerAdditions.h create mode 100644 platform/darwin/src/NSValue+MGLStyleLayerAdditions.h.ejs create mode 100644 platform/darwin/src/NSValue+MGLStyleLayerAdditions.mm create mode 100644 platform/darwin/src/NSValue+MGLStyleLayerAdditions.mm.ejs (limited to 'platform') diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs index cbe38ff6ba..4ead778c03 100644 --- a/platform/darwin/docs/guides/For Style Authors.md.ejs +++ b/platform/darwin/docs/guides/For Style Authors.md.ejs @@ -3,7 +3,7 @@ const iOS = os === 'iOS'; const macOS = os === 'macOS'; const cocoaPrefix = iOS ? 'UI' : 'NS'; - const types = locals.types; + const layers = locals.layers; const renamedProperties = locals.renamedProperties; -%>