Predicates and expressions

Style layers use predicates and expressions to determine what to display and how to format it. Predicates are represented by the same NSPredicate class that filters results from Core Data or items in an NSArray in Objective-C. Predicates are based on expressions, represented by the NSExpression class. Somewhat unusually, style layers also use expressions on their own.

This document discusses the specific subset of the predicate and expression syntax supported by this SDK. For a more general introduction to predicates and expressions, consult the Predicate Programming Guide in Apple developer documentation. For additional detail on how this SDK has extended the NSExpression class, consult the NSExpression(MGLAdditions) section of this documentation.

Using predicates to filter vector data

Most style layer classes display MGLFeature objects that you can show or hide based on the feature’s attributes. Use the MGLVectorStyleLayer.predicate property to include only the features in the source layer that satisfy a condition that you define.

Operators

The following comparison operators are supported:

NSPredicateOperatorType Format string syntax
NSEqualToPredicateOperatorType key = value
key == value
NSGreaterThanOrEqualToPredicateOperatorType key >= value
key => value
NSLessThanOrEqualToPredicateOperatorType key <= value
key =< value
NSGreaterThanPredicateOperatorType key > value
NSLessThanPredicateOperatorType key < value
NSNotEqualToPredicateOperatorType key != value
key <> value
NSBetweenPredicateOperatorType key BETWEEN { 32, 212 }

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.

The following compound operators are supported:

NSCompoundPredicateType Format string syntax
NSAndPredicateType predicate1 AND predicate2
predicate1 && predicate2
NSOrPredicateType predicate1 OR predicate2
predicate1 || predicate2
NSNotPredicateType NOT predicate
!predicate

The following aggregate operators are supported:

NSPredicateOperatorType Format string syntax
NSInPredicateOperatorType key IN { 'iOS', 'macOS', 'tvOS', 'watchOS' }
NSContainsPredicateOperatorType { 'iOS', 'macOS', 'tvOS', 'watchOS' } CONTAINS key

You can use the IN and CONTAINS operators to test whether a value appears in a collection, whether a string is a substring of a larger string, or whether the evaluated feature (SELF) lies within a given MGLShape or MGLFeature. For example, to show one delicious local chain of sandwich shops, but not similarly named steakhouses and pizzerias:

MGLPolygon *cincinnati = [MGLPolygon polygonWithCoordinates:cincinnatiCoordinates count:sizeof(cincinnatiCoordinates) / sizeof(cincinnatiCoordinates[0])];
deliLayer.predicate = [NSPredicate predicateWithFormat:@"class = 'food_and_drink' AND name CONTAINS 'Izzy' AND SELF IN %@", cincinnati];
let cincinnati = MGLPolygon(coordinates: &cincinnatiCoordinates, count: UInt(cincinnatiCoordinates.count))
deliLayer.predicate = NSPredicate(format: "class = 'food_and_drink' AND name CONTAINS 'Izzy' AND SELF IN %@", cincinnati)

The following combinations of comparison operators and modifiers are supported:

NSComparisonPredicateModifier NSPredicateOperatorType Format string syntax
NSAllPredicateModifier NSNotEqualToPredicateOperatorType ALL haystack != needle
NSAnyPredicateModifier NSEqualToPredicateOperatorType ANY haystack = needle
SOME haystack = needle

The following comparison predicate options are supported for comparison and aggregate operators that are used in the predicate:

NSComparisonPredicateOptions Format string syntax
NSCaseInsensitivePredicateOption 'QUEBEC' =[c] 'Quebec'
NSDiacriticInsensitivePredicateOption 'Québec' =[d] 'Quebec'

Other comparison predicate options are unsupported, namely l (for locale sensitivity) and n (for normalization). A comparison is locale-sensitive as long as it is case- or diacritic-insensitive. Comparison predicate options are not supported in conjunction with comparison modifiers like ALL and ANY.

Operands

Operands in predicates can be variables, key paths, or almost anything else that can appear inside an expression.

Automatic type casting is not performed. Therefore, a feature only matches a predicate if its value for the attribute in question is of the same type as the value specified in the predicate. Use the CAST() operator to convert a key path or variable into a matching type:

  • To cast a value to a number, use CAST(key, 'NSNumber').
  • To cast a value to a string, use CAST(key, 'NSString').
  • To cast a value to a color, use CAST(key, 'UIColor') on iOS and CAST(key, 'NSColor') on macOS.
  • To cast an NSColor or UIColor object to an array, use CAST(noindex(color), 'NSArray').

For details about the predicate format string syntax, consult the “Predicate Format String Syntax” chapter of the Predicate Programming Guide in Apple developer documentation.

Using expressions to configure layout and paint attributes

An expression can contain subexpressions of various types. Each of the supported types of expressions is discussed below.

Constant values

A constant value can be of any of the following types:

In Objective-C In Swift
NSColor (macOS)
UIColor (iOS)
NSColor (macOS)
UIColor (iOS)
NSString String
NSString String
NSNumber.boolValue NSNumber.boolValue
NSNumber.doubleValue NSNumber.doubleValue
NSArray<NSNumber> [Float]
NSArray<NSString> [String]
NSValue.CGVectorValue (iOS)
NSValue containing CGVector (macOS)
NSValue.cgVectorValue (iOS)
NSValue containing CGVector (macOS)
NSValue.UIEdgeInsetsValue (iOS)
NSValue.edgeInsetsValue (macOS)
NSValue.uiEdgeInsetsValue (iOS)
NSValue.edgeInsetsValue (macOS)

For literal floating-point values, use -[NSNumber numberWithDouble:] instead of -[NSNumber numberWithFloat:] to avoid precision issues.

Key paths

A key path expression refers to an attribute of the MGLFeature object being evaluated for display. For example, if a polygon’s MGLFeature.attributes dictionary contains the floorCount key, then the key path floorCount refers to the value of the floorCount attribute when evaluating that particular polygon.

The following special attributes are also available on features that are produced as a result of clustering multiple point features together in a shape source:

AttributeTypeMeaning
cluster Bool True if the feature is a point cluster. If the attribute is false (or not present) then the feature should not be considered a cluster.
cluster_id Number Identifier for the point cluster.
point_count Number The number of point features in a given cluster.

Some characters may not be used directly as part of a key path in a format string. For example, if a feature’s attribute is named ISO 3166-1:2006, an expression format string of lowercase(ISO 3166-1:2006) or a predicate format string of ISO 3166-1:2006 == 'US-OH' would raise an exception. Instead, use a %K placeholder or the +[NSExpression expressionForKeyPath:] initializer:

[NSPredicate predicateWithFormat:@"%K == 'US-OH'", @"ISO 3166-1:2006"];
[NSExpression expressionForFunction:@"lowercase:"
                          arguments:@[[NSExpression expressionForKeyPath:@"ISO 3166-1:2006"]]]
NSPredicate(format: "%K == 'US-OH'", "ISO 3166-1:2006")
NSExpression(forFunction: "lowercase:",
             arguments: [NSExpression(forKeyPath: "ISO 3166-1:2006")])

Functions

Of the functions predefined by the +[NSExpression expressionForFunction:arguments:] method, the following subset is supported in layer attribute values:

Initializer parameter Format string syntax
average: average({1, 2, 2, 3, 4, 7, 9})
sum: sum({1, 2, 2, 3, 4, 7, 9})
count: count({1, 2, 2, 3, 4, 7, 9})
min: min({1, 2, 2, 3, 4, 7, 9})
max: max({1, 2, 2, 3, 4, 7, 9})
add:to: 1 + 2
from:subtract: 2 - 1
multiply:by: 1 * 2
divide:by: 1 / 2
modulus:by: modulus:by:(1, 2)
sqrt: sqrt(2)
log: log(10)
ln: ln(2)
raise:toPower: 2 ** 2
exp: exp(0)
ceiling: ceiling(0.99999)
abs: abs(-1)
trunc: trunc(6378.1370)
floor: floor(-0.99999)
uppercase: uppercase('Elysian Fields')
lowercase: lowercase('DOWNTOWN')
noindex: noindex(0 + 2 + c)
length: length('Wapakoneta')
castObject:toType: CAST(ele, 'NSString')
CAST(ele, 'NSNumber')

A number of Mapbox-specific functions are also available.

The following predefined functions are not supported:

Initializer parameter Format string syntax
median: median({1, 2, 2, 3, 4, 7, 9})
mode: mode({1, 2, 2, 3, 4, 7, 9})
stddev: stddev({1, 2, 2, 3, 4, 7, 9})
random random()
randomn: randomn(10)
now now()
bitwiseAnd:with: bitwiseAnd:with:(5, 3)
bitwiseOr:with: bitwiseOr:with:(5, 3)
bitwiseXor:with: bitwiseXor:with:(5, 3)
leftshift:by: leftshift:by:(23, 1)
rightshift:by: rightshift:by:(23, 1)
onesComplement: onesComplement(255)
distanceToLocation:fromLocation: distanceToLocation:fromLocation:(there, here)

Conditionals

Conditionals are supported via the built-in +[NSExpression expressionForConditional:trueExpression:falseExpression:] method and TERNARY() operator. If you need to express multiple cases (“else-if”), you can either nest a conditional within a conditional or use the MGL_IF() or MGL_MATCH() function.

Aggregates

Aggregate expressions can contain arrays of expressions. In some cases, it is possible to use the array itself instead of wrapping the array in an aggregate expression.

Variables

The following variables are defined by this SDK for use with style layers:

VariableTypeMeaning
$featureIdentifier Any GeoJSON data type A value that uniquely identifies the feature in the containing source. This variable corresponds to the NSExpression.featureIdentifierVariableExpression property.
$geometryType String The type of geometry represented by the feature. A feature’s type is one of the following strings:
  • Point for point features, corresponding to the MGLPointAnnotation class
  • LineString for polyline features, corresponding to the MGLPolyline class
  • Polygon for polygon features, corresponding to the MGLPolygon class
This variable corresponds to the NSExpression.geometryTypeVariableExpression property.
$heatmapDensity Number The kernel density estimation of a screen point in a heatmap layer; in other words, a relative measure of how many data points are crowded around a particular pixel. This variable can only be used with the heatmapColor property. This variable corresponds to the NSExpression.heatmapDensityVariableExpression property.
$zoomLevel Number The current zoom level. In style layout and paint properties, this variable may only appear as the target of a top-level interpolation or step expression. This variable corresponds to the NSExpression.zoomLevelVariableExpression property.
$lineProgress Number A number that indicates the relative distance along a line at a given point along the line. This variable evaluates to 0 at the beginning of the line and 1 at the end of the line. It can only be used with the `MGLLineStyleLayer.lineGradient` property. It corresponds to the NSExpression.lineProgressVariableExpression property.

In addition to these variables, you can define your own variables and refer to them elsewhere in the expression. The syntax for defining a variable makes use of a Mapbox-specific function that takes an NSDictionary as an argument:

[NSExpression expressionWithFormat:@"MGL_LET('floorCount', 2, $floorCount + 1)"];
NSExpression(format: "MGL_LET(floorCount, 2, $floorCount + 1)")

Mapbox-specific functions

For compatibility with the Mapbox Style Specification, the following functions are defined by this SDK. When setting a style layer property, you can call these functions just like the predefined functions above, using either the +[NSExpression expressionForFunction:arguments:] method or a convenient format string syntax:

mgl_does:have:

Selector:
mgl_does:have:
Format string syntax:
mgl_does:have:(SELF, '🧀🍔') or mgl_does:have:(%@, '🧀🍔')

Returns a Boolean value indicating whether the dictionary has a value for the key or whether the evaluated object (SELF) has a value for the feature attribute. Compared to the mgl_has: custom function, that function’s target is instead passed in as the first argument to this function. Both functions are equivalent to the syntax key != NIL or %@[key] != NIL but can be used outside of a predicate.

mgl_interpolate:withCurveType:parameters:stops:

Selector:
mgl_interpolate:withCurveType:parameters:stops:
Format string syntax:
mgl_interpolate:withCurveType:parameters:stops:(x, 'linear', nil, %@)

Produces continuous, smooth results by interpolating between pairs of input and output values (“stops”). Compared to the mgl_interpolateWithCurveType:parameters:stops: custom function, the input expression (that function’s target) is instead passed in as the first argument to this function.

mgl_step:from:stops:

Selector:
mgl_step:from:stops:
Format string syntax:
mgl_step:from:stops:(x, 11, %@)

Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of input and output values (“stops”). Compared to the mgl_stepWithMinimum:stops: custom function, the input expression (that function’s target) is instead passed in as the first argument to this function.

mgl_join:

Selector:
mgl_join:
Format string syntax:
mgl_join({'Old', 'MacDonald'})

Returns the result of concatenating together all the elements of an array in order. Compared to the stringByAppendingString: custom function, this function takes only one argument, which is an aggregate expression containing the strings to concatenate.

mgl_acos:

Selector:
mgl_acos:
Format string syntax:
mgl_acos(1)

Returns the arccosine of the number.

This function corresponds to the acos operator in the Mapbox Style Specification.

mgl_asin:

Selector:
mgl_asin:
Format string syntax:
mgl_asin(0)

Returns the arcsine of the number.

This function corresponds to the asin operator in the Mapbox Style Specification.

mgl_atan:

Selector:
mgl_atan:
Format string syntax:
mgl_atan(20)

Returns the arctangent of the number.

This function corresponds to the atan operator in the Mapbox Style Specification.

mgl_cos:

Selector:
mgl_cos:
Format string syntax:
mgl_cos(0)

Returns the cosine of the number.

This function corresponds to the cos operator in the Mapbox Style Specification.

mgl_log2:

Selector:
mgl_log2:
Format string syntax:
mgl_log2(1024)

Returns the base-2 logarithm of the number.

This function corresponds to the log2 operator in the Mapbox Style Specification.

mgl_round:

Selector:
mgl_round:
Format string syntax:
mgl_round(1.5)

Returns the number rounded to the nearest integer. If the number is halfway between two integers, this function rounds it away from zero.

This function corresponds to the round operator in the Mapbox Style Specification.

mgl_sin:

Selector:
mgl_sin:
Format string syntax:
mgl_sin(0)

Returns the sine of the number.

This function corresponds to the sin operator in the Mapbox Style Specification.

mgl_tan:

Selector:
mgl_tan:
Format string syntax:
mgl_tan(0)

Returns the tangent of the number.

This function corresponds to the tan operator in the Mapbox Style Specification.

mgl_coalesce:

Selector:
mgl_coalesce:
Format string syntax:
mgl_coalesce({x, y, z})

Returns the first non-nil value from an array of expressions.

This function corresponds to the coalesce operator in the Mapbox Style Specification.

mgl_attributed:

Selector:
mgl_attributed:
Format string syntax:
mgl_attributed({x, y, z})

Concatenates and returns the array of MGLAttributedExpression objects, for use with the MGLSymbolStyleLayer.text property.

MGLAttributedExpression.attributes valid attributes.

Key Value Type
MGLFontNamesAttribute An NSExpression evaluating to an NSString array.
MGLFontScaleAttribute An NSExpression evaluating to an NSNumber value.
MGLFontColorAttribute An NSExpression evaluating to an UIColor (iOS) or NSColor (macOS).

This function corresponds to the format operator in the Mapbox Style Specification.

MGL_LET

Selector:
MGL_LET:
Format string syntax:
MGL_LET('age', uppercase('old'), 'name', uppercase('MacDonald'), mgl_join({$age, $name}))
Arguments:
Any number of variable names interspersed with their assigned NSExpression values, followed by an NSExpression that may contain references to those variables.

Returns the result of evaluating an expression with the given variable values. Compared to the mgl_expressionWithContext: custom function, this function takes the variable names and values inline before the expression that contains references to those variables.

MGL_MATCH

Selector:
MGL_MATCH:
Format string syntax:
MGL_MATCH(x, 0, 'zero match', 1, 'one match', 2, 'two match', 'default')
Arguments:
An input expression, then any number of argument pairs, followed by a default expression. Each argument pair consists of a constant value followed by an expression to produce as a result of matching that constant value. If the input value is an aggregate expression, then any of the constant values within that aggregate expression result in the following argument. This is shorthand for specifying an argument pair for each of the constant values within that aggregate expression. It is not possible to match the aggregate expression itself.

Returns the result of matching the input expression against the given constant values.

This function corresponds to the +[NSExpression(MGLAdditions) mgl_expressionForMatchingExpression:inDictionary:defaultExpression:] method and the match operator in the Mapbox Style Specification.

MGL_IF

Selector:
MGL_IF:
Format string syntax:
MGL_IF(1 = 2, YES, 2 = 2, YES, NO)
Arguments:
Alternating NSPredicate conditionals and resulting expressions, followed by a default expression.

Returns the first expression that meets the condition; otherwise, the default value. Unlike +[NSExpression expressionForConditional:trueExpression:falseExpression:] or the TERNARY() syntax, this function can accept multiple “if else” conditions and is supported on iOS 8.x and macOS 10.10.x; however, each conditional passed into this function must be wrapped in a constant expression.

This function corresponds to the +[NSExpression(MGLAdditions) mgl_expressionForConditional:trueExpression:falseExpresssion:] method and the case operator in the Mapbox Style Specification.

MGL_FUNCTION

Selector:
MGL_FUNCTION:
Format string syntax:
MGL_FUNCTION('typeof', mystery)
Arguments:
Any arguments required by the expression operator.

An expression exactly as defined by the Mapbox Style Specification.

Custom functions

The following custom functions are also available with the +[NSExpression expressionForFunction:selectorName:arguments:] method or the FUNCTION() format string syntax.

Some of these functions are defined as methods on their respective target classes, but you should not call them directly outside the context of an expression, because the result may differ from the evaluated expression’s result or may result in undefined behavior.

The Mapbox Style Specification defines some operators for which no custom function is available. To use these operators in an NSExpression, call the MGL_FUNCTION() function with the same arguments that the operator expects.

boolValue

Selector:
boolValue
Format string syntax:
FUNCTION(1, 'boolValue')
Target:
An NSExpression that evaluates to a number or string.
Arguments:
None.

A Boolean representation of the target: FALSE when then input is an empty string, 0, FALSE, NIL, or NaN, otherwise TRUE.

mgl_has:

Selector:
mgl_has:
Format string syntax:
FUNCTION($featureAttributes, 'mgl_has:', '🧀🍔')
Target:
An NSExpression that evaluates to an NSDictionary or the evaluated object (SELF).
Arguments:
An NSExpression that evaluates to an NSString representing the key to look up in the dictionary or the feature attribute to look up in the evaluated object (see MGLFeature.attributes).

true if the dictionary has a value for the key or if the evaluated object has a value for the feature attribute.

This function corresponds to the has operator in the Mapbox Style Specification. See also the mgl_does:have: function, which is used on its own without the FUNCTION() operator. You can also check whether an object has an attribute by comparing the key path to NIL, for example cheeseburger != NIL or burger.cheese != NIL

mgl_expressionWithContext:

Selector:
mgl_expressionWithContext:
Format string syntax:
FUNCTION($ios + $macos, 'mgl_expressionWithContext:', %@) with a dictionary containing ios and macos keys
Target:
An NSExpression that may contain references to the variables defined in the context dictionary.
Arguments:
An NSDictionary with NSStrings as keys and NSExpressions as values. Each key is a variable name and each value is the variable’s value within the target expression.

The target expression with variable subexpressions replaced with the values defined in the context dictionary.

This function corresponds to the let operator in the Mapbox Style Specification. See also the MGL_LET function, which is used on its own without the FUNCTION() operator.

mgl_interpolateWithCurveType:parameters:stops:

Selector:
mgl_interpolateWithCurveType:parameters:stops:
Format string syntax:
FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', NIL, %@) with a dictionary containing zoom levels or other constant values as keys
Target:
An NSExpression that evaluates to a number and contains a variable or key path expression.
Arguments:
The first argument is one of the following strings denoting curve types: linear, exponential, or cubic-bezier. The second argument is an expression providing parameters for the curve:
  • If the curve type is linear, the argument is NIL.
  • If the curve type is exponential, the argument is an expression that evaluates to a number, specifying the base of the exponential interpolation.
  • If the curve type is cubic-bezier, the argument is an array or aggregate expression containing four expressions, each evaluating to a number. The four numbers are control points for the cubic Bézier curve.
The third argument is an NSDictionary object representing the interpolation’s stops, with numeric zoom levels as keys and expressions as values.

A value interpolated along the continuous mathematical function defined by the arguments, with the target as the input to the function.

The input expression is matched against the keys in the stop dictionary. The keys may be feature attribute values, zoom levels, or heatmap densities. The values may be constant values or NSExpression objects. For example, you can use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors yellow, orange, and red as the values.

This function corresponds to the +[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:] method and the interpolate operator in the Mapbox Style Specification. See also the mgl_interpolate:withCurveType:parameters:stops: function, which is used on its own without the FUNCTION() operator.

mgl_numberWithFallbackValues:

Selector:
mgl_numberWithFallbackValues:, doubleValue, floatValue, or decimalValue
Format string syntax:
FUNCTION(ele, 'mgl_numberWithFallbackValues:', 0)
Target:
An NSExpression that evaluates to a Boolean value, number, or string.
Arguments:
Zero or more NSExpressions, each evaluating to a Boolean value or string.

A numeric representation of the target:

  • If the target is NIL or FALSE, the result is 0.
  • If the target is true, the result is 1.
    • If the target is a string, it is converted to a number as specified by the “ToNumber Applied to the String Type” algorithm of the ECMAScript Language Specification.
    • If multiple values are provided, each one is evaluated in order until the first successful conversion is obtained.

This function corresponds to the to-number operator in the Mapbox Style Specification. You can also cast a value to a number by passing the value and the string NSNumber into the CAST() operator.

mgl_stepWithMinimum:stops:

Selector:
mgl_stepWithMinimum:stops:
Format string syntax:
FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', 0, %@) with a dictionary with zoom levels or other constant values as keys
Target:
An NSExpression that evaluates to a number and contains a variable or key path expression.
Arguments:
The first argument is an expression that evaluates to a number, specifying the minimum value in case the target is less than any of the stops in the second argument. The second argument is an NSDictionary object representing the interpolation’s stops, with numeric zoom levels as keys and expressions as values.

The output value of the stop whose key is just less than the evaluated target, or the minimum value if the target is less than the least of the stops’ keys.

The input expression is matched against the keys in the stop dictionary. The keys may be feature attribute values, zoom levels, or heatmap densities. The values may be constant values or NSExpression objects. For example, you can use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors yellow, orange, and red as the values.

This function corresponds to the +[NSExpression(MGLAdditions) mgl_expressionForSteppingExpression:fromExpression:stops:] method and the step operator in the Mapbox Style Specification.

stringByAppendingString:

Selector:
stringByAppendingString:
Format string syntax:
FUNCTION('Old', 'stringByAppendingString:', 'MacDonald')
Target:
An NSExpression that evaluates to a string.
Arguments:
One or more NSExpressions, each evaluating to a string.

The target string with each of the argument strings appended in order.

This function corresponds to the -[NSExpression(MGLAdditions) mgl_expressionByAppendingExpression:] method and is similar to the concat operator in the Mapbox Style Specification. See also the mgl_join: function, which concatenates multiple expressions and is used on its own without the FUNCTION() operator.

stringValue

Selector:
stringValue
Format string syntax:
FUNCTION(ele, 'stringValue')
Target:
An NSExpression that evaluates to a Boolean value, number, or string.
Arguments:
None.

A string representation of the target:

  • If the target is NIL, the result is the empty string.
  • If the target is a Boolean value, the result is the string true or false.
  • If the target is a number, it is converted to a string as specified by the “NumberToString” algorithm of the ECMAScript Language Specification.
  • If the target is a color, it is converted to a string of the form rgba(r,g,b,a), where r, g, and b are numerals ranging from 0 to 255 and a ranges from 0 to 1.
  • Otherwise, the target is converted to a string in the format specified by the JSON.stringify() function of the ECMAScript Language Specification.

This function corresponds to the to-string operator in the Mapbox Style Specification. You can also cast a value to a string by passing the value and the string NSString into the CAST() operator.