My application stores data, which includes coordinates and other info, in a local database. Due to the number of data points, the application uses clustering to display the data with Mapbox on iOS. Some of the marker styling is based on data, which can change on the run. Map setup is:
// fetch data from DB
let dataArray: [MyData] = fetchData()
// build features from data array
var features = [MGLPointFeature]()
dataArray.forEach({ (data) in
let feature = MGLPointFeature()
feature.identifier = data.id
feature.coordinate = CLLocationCoordinate2D(latitude: data.lat, longitude: data.lng)
// our attributes
feature.attributes = [
"amount": data.amount
"marked": false
]
features.append(feature)
})
// make and add source
let source = MGLShapeSource(identifier: "MySourceId", features: features, options: [
.clustered: true
])
style.addSource(source)
// regular marker layer
let layer = MGLSymbolStyleLayer(identifier: "unclustered", source: source)
layer.iconImageName = NSExpression(forConstantValue: "MyIcon")
layer.text = NSExpression(forKeyPath: "amount")
layer.iconScale = NSExpression(forMGLConditional: NSPredicate(format: "%@ == true", NSExpression(forKeyPath: "marked")), trueExpression: NSExpression(forConstantValue: 2.0), falseExpression: NSExpression(forConstantValue: 1.0))
layer.predicate = NSPredicate(format: "cluster != YES")
style.addLayer(layer)
// point_count layers
...
The above code is simplified to help illustrate the concept more clearly. Array of MGLPoint is used because data is stored in DB, so we don't have a GeoJSON file or a URL. MGLShapeSource is used because clustering is required, and that's what I found in the examples. MGLShapeSource constructor taking "features" as a parameter is used because that's the one that matches the data I have. The regular marker layer is setup to show different size icons based on the value of "marked" attribute in iconScale.
During runtime, the value of "marked" attribute can change (for example, when a marker is tapped), and the corresponding icon's size needs to be updated to reflect the change in "marker" value. However, I am unable to figure out how to change the marker attribute value. MGPShapeSource only shows access to shape and URL, neither of which is the features array I initialized the source with. I need to access the features array the source was constructed with, change the marker value, and have the marker icons updated.
I have thought about remaking the source on each data change. But with the number of markers involved, this would perform poorly. Plus I believe I would also need to remake all of the style layers, as they're constructed with the actual source object, which would make this perform even worse.
I need help figuring out how to change the attribute value of MGLPointFeature within MGLShapeSource during runtime and have the map updated.