mapbox / mapbox/mapbox-maps-ios

feature-state styling not working.

Open
#2,046 9 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

auto-triaged bug :beetle: needs info v11
Dominant language
Swift
Stars
601
Forks
196
PR merge metrics
No merged PRs in 30d

Description

## Environment

- Xcode version: 15.0.1
- iOS version: 17.0.1
- Devices affected: all
- Maps SDK Version: 11.0.0-rc.1

## Observed behavior and steps to reproduce

I have created a custom map style on Mapbox Studio and uploaded a GeoJSON with several multipolygon features, the file looks like this:

```json
{
"type": "FeatureCollection",
"name": "AD_micro-regions",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"type": "Feature",
"id": "AD-01_low_high",
"properties": {
"id": "AD-01",
"elevation": "low_high"
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [...]
}
},
... other fetures
]
```

I defined a custom styling for the layer I created so that each feature will be colored according to the `danger_level` feature state (1, 2, 3, 4, 5):

```
[
"match",
["feature-state", "danger_level"],
[1],
"rgb(134, 231, 75)",
[2],
"rgb(249, 219, 73)",
[3],
"rgb(235, 134, 52)",
[4],
"rgb(216, 69, 49)",
[5],
"rgb(184, 64, 46)",
"rgba(0, 0, 0, 0)"
]
```

Now my plan would be to set the `danger_level` for each feature from the iOS SDK, but I can't really find a way to do it.

I tried using `setFeatureState` but it has no effect:

```swift
map.setFeatureState(
sourceId: "composite",
//sourceLayerId: "micro-regions_elevation-2p16jz",
featureId: "AD-01_low_high",
state: ["danger_level": 4],
callback: { result in
// This returns `success()`
print(result)

map.getFeatureState(
sourceId: "composite",
featureId: "AD-01_low_high",
callback: { state in
// This correctly prints `success(["danger_level": 4])`
// but the map style is not updated
print(state)
}
)
}
)
```

The code above has no effect, the state seems to be set correctly but no updates happen on the rendered map.

If I also specify the `sourceLayerId`, the second `print` statement returns an empty dictionary.

If I print `map.allSourceIdentifiers` I only see this:

```
[
MapboxMaps.SourceInfo(id: "composite", type: MapboxMaps.SourceType(rawValue: "vector")),
MapboxMaps.SourceInfo(id: "6D9AE", type: MapboxMaps.SourceType(rawValue: "geojson"))
]
```

My map has two geojson layers, not one, and 6D9AE changes id on each render. I tried using `map.allSourceIdentifiers.last!.id` as `sourceId` for the `setFeatureState` call but it had no effect.

I tried to retrieve the layer with `map.layer(withId: "micro-regions_elevation")` and it correctly returned the layer data:

```
FillLayer(id: "micro-regions_elevations", type: MapboxMaps.LayerType(rawValue: "fill"), filter: nil, source: Optional("composite"), sourceLayer: Optional("micro-regions_elevation-2p16jz"), slot: nil, minZoom: nil, maxZoom: nil, visibility: MapboxMaps.Value.constant(MapboxMaps.Visibility.visible), fillSortKey: nil, fillAntialias: nil, fillColor: Optional(MapboxMaps.Value.expression([match, [get, danger_level], 1, [rgba, 134.0, 231.00001525878906, 75.0, 1.0], 2, [rgba, 249.00001525878906, 219.00001525878906, 73.0, 1.0], 3, [rgba, 235.00001525878906, 134.0, 52.000003814697266, 1.0], 4, [rgba, 216.00001525878906, 69.0, 49.000003814697266, 1.0], 5, [rgba, 184.0, 64.0, 46.0, 1.0], [rgba, 0.0, 0.0, 0.0, 0.0]])), fillColorTransition: nil, fillEmissiveStrength: nil, fillEmissiveStrengthTransition: nil, fillOpacity: Optional(MapboxMaps.Value.constant(0.5)), fillOpacityTransition: nil, fillOutlineColor: Optional(MapboxMaps.Value.constant(MapboxMaps.StyleColor(rawValue: "rgba(0.00, 0.00, 0.00, 0.00)"))), fillOutlineColorTransition: nil, fillPattern: nil, fillTranslate: nil, fillTranslateTransition: nil, fillTranslateAnchor: nil)
```

But I still get the same result.

I also tried this alternative fill color formula wit the same result though:

```
[
"case",
["==", ["feature-state", "danger_level"], 1],
"rgb(134, 231, 75)",
["==", ["feature-state", "danger_level"], 2],
"rgb(249, 219, 73)",
["==", ["feature-state", "danger_level"], 3],
"rgb(235, 134, 52)",
["==", ["feature-state", "danger_level"], 4],
"rgb(216, 69, 49)",
["==", ["feature-state", "danger_level"], 5],
"rgb(184, 64, 46)",
"rgba(0, 0, 0, 0)"
]
```

This is my map style ID for reference: mapbox://styles/fezvrasta/clol7m5uj008q01qocvyg1fzx

What am I doing wrong?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue with the shown setFeatureState and getFeatureState calls, comparing the composite source, sourceLayerId, featureId, and the rendered FillLayer configuration. Check the Mapbox Maps iOS feature-state API and the referenced style to determine why the stored danger_level does not affect the fill color; done means the rendered multipolygon colors change for each feature state.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, swift
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.