Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Crash when filtering MGLFillStyleLayer with an NSPredicate #13527

Closed
riastrad opened this issue Dec 7, 2018 · 3 comments
Closed

Crash when filtering MGLFillStyleLayer with an NSPredicate #13527

riastrad opened this issue Dec 7, 2018 · 3 comments
Assignees
Labels
bug iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS

Comments

@riastrad
Copy link
Contributor

riastrad commented Dec 7, 2018

When applying a predicate with an IN <array> statement that has 10-digit long NSNumbers in the array, a crash occurs if the array has 4 or more items in it. Oddly enough, if you trim the values of the numbers in the array down to 4-digits then the crash no longer occurs.

Steps to reproduce

  1. Create an MGLFillStyleLayer
  2. Apply a predicate to the layer with an array of NSNumbers. For example:
 layer.predicate = NSPredicate(format: "CAST($featureIdentifier, 'NSNumber') IN %@", [3002970001, 3004140052, 3002950027, 3002970033])
  1. Add that layer to your mapView's MGLStyle

Expected behavior

Predicate should filter features in the layer by ID.

Actual behavior

The app crashes with the following error:

'NSInvalidArgumentException', reason: 'Invalid filter value: [2]: Branch labels must be unique.'

Configuration

Mapbox SDK versions: 4.6.0
iOS/macOS versions: iOS 12.1
Device/simulator models: iPhone XR
Xcode version: 10.1

cc: @mapbox/maps-ios

@riastrad riastrad added bug iOS Mapbox Maps SDK for iOS labels Dec 7, 2018
@1ec5
Copy link
Contributor

1ec5 commented Dec 7, 2018

My first guess would be a precision problem in the code that converts NSExpression to JSON. The NSExpression.mgl_jsonExpressionObject property is useful for debugging these translation issues.

@riastrad
Copy link
Contributor Author

riastrad commented Dec 13, 2018

Running mgl_jsonExpressionObject generates the following output:

(
    match,
        (
        "to-number",
                (
            id
        )
    ),
        (
        3002970001,
        3004140052,
        3002950027,
        3002970033
    ),
    1,
    0
)

I'm not seeing anything inherently wrong with this output, but my eye's are also not that fresh at this point.

EDIT: modifying json to reflect exact output of original predicate in OP

@1ec5
Copy link
Contributor

1ec5 commented Dec 13, 2018

These numbers are being converted to floats instead of doubles, despite the comment:

} else if (_isNumber(value)) {
// Need to cast to a double here as the float is otherwise considered a bool...
return { static_cast<double>(*toNumber(holder)) };
static optional<float> toNumber(const Holder& holder) {
const id value = holder.value;
if (_isNumber(value)) {
return ((NSNumber *)value).floatValue;
} else {
return {};
}
}
static optional<double> toDouble(const Holder& holder) {
const id value = holder.value;
if (_isNumber(value)) {
return ((NSNumber *)value).doubleValue;
} else {
return {};
}
}

These numbers don’t fit in floating-point precision, so we’d want toDouble() to be called here.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug iOS Mapbox Maps SDK for iOS macOS Mapbox Maps SDK for macOS
Projects
None yet
Development

No branches or pull requests

4 participants