Search code examples
iosswiftmapboxmapbox-ios

Different icon for every feature in Feature Collection


I have feature collection geojson. I want to set each of them different icon base to their attributes. But i could not find how. For now i just can set one image for just all layer. Is it possible to set each of feature different icon?

func drawPoint(geoJson : String , id: String) {
    DispatchQueue.global(qos: .background).async(execute: {
        do {
            let data = geoJson.data(using: .utf8)
            let id = "kgm-\(id)"
            guard let shapeCollectionFeature = try MGLShape(data: data!, encoding: String.Encoding.utf8.rawValue) as? MGLShapeCollectionFeature else {
                fatalError("Could not cast to specified MGLShapeCollectionFeature")
            }

            let source = MGLShapeSource(identifier: id, shape: shapeCollectionFeature, options: nil)
            self.mapView.style?.addSource(source)

            let pointLayer = MGLSymbolStyleLayer(identifier: id, source: source)
            let zoomStops = [
                13.49: NSExpression(forConstantValue: 0),
                13.5: NSExpression(forConstantValue: 1)
            ]

            pointLayer.iconOpacity = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", zoomStops)
            pointLayer.iconImageName = NSExpression(forConstantValue: id)
            pointLayer.iconAllowsOverlap = NSExpression(forConstantValue: true)
            self.mapView.style!.addLayer(pointLayer)
        } catch {
            print("GeoJSON parsing failed")
        }
    })
}

Solution

  • You may need to set the image name in the style. This adds the specified image to the style's images.

    If you would like to style to iconImageName based on the value for id, you may also want to try using NSExpression(forKeyPath:) rather than NSExpression(forConstantValue:). For example:

    pointLayer.iconImageName = NSExpression(forKeyPath: id)

    Some examples that you may find helpful:

    Also, you may want to add the source and layer to the style on the main thread. Adding style layers on a background thread can result in unexpected behavior.