Update Mapbox Studio defined features' properties from iOS SDK?

135 views Asked by At

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

{
  "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:

map.setFeatureState(
  sourceId: "composite",
  //sourceLayerId: "micro-regions_elevation-2p16jz",
  featureId: "AD-01_low_high",
  state: ["danger_level": 4],
  callback: { result in
    // This returns `success(<null>)`
    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<MapboxMaps.Visibility>.constant(MapboxMaps.Visibility.visible), fillSortKey: nil, fillAntialias: nil, fillColor: Optional(MapboxMaps.Value<MapboxMaps.StyleColor>.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<Swift.Double>.constant(0.5)), fillOpacityTransition: nil, fillOutlineColor: Optional(MapboxMaps.Value<MapboxMaps.StyleColor>.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)"
]

What am I doing wrong? I'm using SDK 11.0.0-rc.1

2

There are 2 answers

0
Fez Vrasta On BEST ANSWER

I opened an issue on the project GitHub page and it ended up being a bug in the SDK, there's nothing wrong with my code apparently.

https://github.com/mapbox/mapbox-maps-ios/issues/2046#issuecomment-1804795992

1
user16930239 On

call the following code to update layer with filter:

mapView.mapboxMap.style.updateLayer(withId:type:update:)

An example from Mapbox github

use Expressions and test them firstly on Mapbox Studio

func applyMYFilter(for types: [String]) throws {
    try updateMapLayer(withId: "poi-label", ofType: SymbolLayer.self) { layer in
        layer.filter = Expression.match {
            Expression.get(.string("class")),
            types,
            true,
            false
        }
    }
}

func updateMapLayer(withId layerId: String, ofType layerType: SymbolLayer.Type, updateHandler: (inout SymbolLayer) throws -> Void) throws {
    try mapView.mapboxMap.style.updateLayer(withId: layerId, type: layerType) { layer in
        try updateHandler(&layer)
    }
}