mapbox-maps-ios icon indicating copy to clipboard operation
mapbox-maps-ios copied to clipboard

`style.addLayer()` fails when specifying a `textFont` in `FormatOptions`

Open jake-low opened this issue 3 years ago • 0 comments

Environment

  • Xcode version: 13.2.1
  • iOS version: 15.2.1
  • Devices affected: iPhone 13
  • Maps SDK Version: 10.3.0-rc.1

Observed behavior and steps to reproduce

This code works; the layer is visible on the map as expected.

var peaksLayer = SymbolLayer(id: "peaks-layer")
peaksLayer.source = "my-source-id"
peaksLayer.sourceLayer = "peaks"
peaksLayer.textField = .expression(
  Exp(.format) {
    Exp(.get) { "name" }
    FormatOptions(fontScale: 1.2)
    "\n"
    FormatOptions()
    Exp(.get) { "elevation" }
    FormatOptions(fontScale: 0.8)
  }
)

try mapView.mapboxMap.style.addLayer(peaksLayer) // succeeds

However, if we add a textFont to one of the format options, addLayer will throw an error.

var peaksLayer = SymbolLayer(id: "peaks-layer")
peaksLayer.source = "my-source-id"
peaksLayer.sourceLayer = "peaks"
peaksLayer.textField = .expression(
  Exp(.format) {
    Exp(.get) { "name" }
    FormatOptions(fontScale: 1.2)
    "\n"
    FormatOptions()
    Exp(.get) { "elevation" }
    FormatOptions(fontScale: 0.8, textFont: ["MyItalicFont"]) // add a font override so the elevation shows in italic
  }
)

try mapView.mapboxMap.style.addLayer(peaksLayer) // throws an error

The error thrown is:

MapboxMaps.StyleError(rawValue: "[1][0]: Unknown expression \"MyItalicFont\". If you wanted a literal array, use [\"literal\", [...]].")

Expected behavior

Since it's not possible to pass an expression (such as Exp(.literal) { ["MyItalicFont"] }) into FormatOptions (its initializer takes a plain old [String]?), I therefore expected that the SDK would handle wrapping the literal array for me. But it looks like that hasn't been implemented, which causes the renderer to reject the layer.

A related question

Is FormatOptions intended to support computing its values with sub-expressions? This Mapbox GL JS example uses 'text-font': ['literal', ['DIN Offc Pro Italic', 'Arial Unicode MS Regular']], which implies to me that other expressions would be supported there too. If that's the case, I think the signature of FormatOptions.init() needs to change:

- public init(fontScale: Double? = nil, textFont: [String]? = nil, textColor: UIColor? = nil) {
+ public init(fontScale: Value<Double>? = nil, textFont: Value<String>? = nil, textColor: Value<StyleColor>? = nil) {

But accepting this limitation for now, it still seems to be impossible to use a FormatOptions that specifies a textFont.

jake-low avatar Feb 09 '22 01:02 jake-low