Clarify how the different mapLibre URLs are used.

This commit is contained in:
Stefan Ceriu
2025-11-10 15:13:19 +02:00
committed by Stefan Ceriu
parent 6465730638
commit dd95a4313a
5 changed files with 47 additions and 45 deletions
@@ -65,7 +65,7 @@ struct MapLibreMapView: UIViewRepresentable {
// Don't set the same value twice. Otherwise, if there is an error loading the map, a loop // Don't set the same value twice. Otherwise, if there is an error loading the map, a loop
// is caused as the `error` binding being set, which triggers this update, which sets a // is caused as the `error` binding being set, which triggers this update, which sets a
// new URL, which causes another error, and so it goes on round and round in a circle. // new URL, which causes another error, and so it goes on round and round in a circle.
let dynamicMapURL = mapURLBuilder.dynamicMapURL(for: .init(colorScheme)) let dynamicMapURL = mapURLBuilder.interactiveMapURL(for: .init(colorScheme))
if mapView.styleURL != dynamicMapURL { if mapView.styleURL != dynamicMapURL {
mapView.styleURL = dynamicMapURL mapView.styleURL = dynamicMapURL
} }
@@ -86,7 +86,7 @@ struct MapLibreMapView: UIViewRepresentable {
} }
private func makeMapView() -> MGLMapView { private func makeMapView() -> MGLMapView {
let mapView = MGLMapView(frame: .zero, styleURL: mapURLBuilder.dynamicMapURL(for: colorScheme == .dark ? .dark : .light)) let mapView = MGLMapView(frame: .zero, styleURL: mapURLBuilder.interactiveMapURL(for: colorScheme == .dark ? .dark : .light))
mapView.logoViewPosition = .topLeft mapView.logoViewPosition = .topLeft
mapView.attributionButtonPosition = .topLeft mapView.attributionButtonPosition = .topLeft
mapView.attributionButtonMargins = .init(x: mapView.logoView.frame.maxX + 8, y: mapView.logoView.center.y / 2) mapView.attributionButtonMargins = .init(x: mapView.logoView.frame.maxX + 8, y: mapView.logoView.center.y / 2)
@@ -36,7 +36,7 @@ struct MapLibreStaticMapView<PinAnnotation: View>: View {
var body: some View { var body: some View {
GeometryReader { geometry in GeometryReader { geometry in
if let url = mapURLBuilder.staticMapURL(for: colorScheme.mapStyle, if let url = mapURLBuilder.staticMapTileImageURL(for: colorScheme.mapStyle,
coordinates: coordinates, coordinates: coordinates,
zoomLevel: zoomLevel, zoomLevel: zoomLevel,
size: mapSize, // temporary using a fixed size since the refresh doesn't work properly on the UITableView based timeline size: mapSize, // temporary using a fixed size since the refresh doesn't work properly on the UITableView based timeline
@@ -114,9 +114,9 @@ struct MapLibreStaticMapView_Previews: PreviewProvider, TestablePreview {
} }
private struct MapTilerURLBuilderMock: MapTilerURLBuilderProtocol { private struct MapTilerURLBuilderMock: MapTilerURLBuilderProtocol {
func dynamicMapURL(for style: MapTilerStyle) -> URL? { nil } func interactiveMapURL(for style: MapTilerStyle) -> URL? { nil }
func staticMapURL(for style: MapTilerStyle, func staticMapTileImageURL(for style: MapTilerStyle,
coordinates: CLLocationCoordinate2D, coordinates: CLLocationCoordinate2D,
zoomLevel: Double, zoomLevel: Double,
size: CGSize, size: CGSize,
@@ -9,9 +9,9 @@
import CoreLocation import CoreLocation
protocol MapTilerURLBuilderProtocol { protocol MapTilerURLBuilderProtocol {
func dynamicMapURL(for style: MapTilerStyle) -> URL? func interactiveMapURL(for style: MapTilerStyle) -> URL?
func staticMapURL(for style: MapTilerStyle, func staticMapTileImageURL(for style: MapTilerStyle,
coordinates: CLLocationCoordinate2D, coordinates: CLLocationCoordinate2D,
zoomLevel: Double, zoomLevel: Double,
size: CGSize, size: CGSize,
@@ -9,18 +9,20 @@
import CoreLocation import CoreLocation
extension MapTilerConfiguration: MapTilerURLBuilderProtocol { extension MapTilerConfiguration: MapTilerURLBuilderProtocol {
func dynamicMapURL(for style: MapTilerStyle) -> URL? { /// For interactive MGLMap components
var url = makeNewURL(for: style) func interactiveMapURL(for style: MapTilerStyle) -> URL? {
var url = styleURL(for: style)
url?.appendPathComponent("style.json", conformingTo: .json) url?.appendPathComponent("style.json", conformingTo: .json)
return url return url
} }
func staticMapURL(for style: MapTilerStyle, /// Used in the timeline where a full MGLMapView loading is unwanted
func staticMapTileImageURL(for style: MapTilerStyle,
coordinates: CLLocationCoordinate2D, coordinates: CLLocationCoordinate2D,
zoomLevel: Double, zoomLevel: Double,
size: CGSize, size: CGSize,
attribution: MapTilerAttributionPlacement) -> URL? { attribution: MapTilerAttributionPlacement) -> URL? {
var url = makeNewURL(for: style) var url = styleURL(for: style)
url?.appendPathComponent(String(format: "static/%f,%f,%f/%dx%d@2x.png", url?.appendPathComponent(String(format: "static/%f,%f,%f/%dx%d@2x.png",
coordinates.longitude, coordinates.longitude,
coordinates.latitude, coordinates.latitude,
@@ -34,7 +36,7 @@ extension MapTilerConfiguration: MapTilerURLBuilderProtocol {
// MARK: Private // MARK: Private
private func makeNewURL(for style: MapTilerStyle) -> URL? { private func styleURL(for style: MapTilerStyle) -> URL? {
guard let apiKey else { return nil } guard let apiKey else { return nil }
var url: URL = baseURL var url: URL = baseURL
@@ -26,7 +26,7 @@ final class MapTilerURLBuilderTests: XCTestCase {
} }
func testStaticMapBuilder() { func testStaticMapBuilder() {
let url = builder.staticMapURL(for: .light, let url = builder.staticMapTileImageURL(for: .light,
coordinates: .init(latitude: 1, longitude: 2), coordinates: .init(latitude: 1, longitude: 2),
zoomLevel: 5, zoomLevel: 5,
size: .init(width: 300, height: 200), size: .init(width: 300, height: 200),
@@ -37,7 +37,7 @@ final class MapTilerURLBuilderTests: XCTestCase {
} }
func testStaticMapBuilderWithAttribution() { func testStaticMapBuilderWithAttribution() {
let url = builder.staticMapURL(for: .dark, let url = builder.staticMapTileImageURL(for: .dark,
coordinates: .init(latitude: 1, longitude: 2), coordinates: .init(latitude: 1, longitude: 2),
zoomLevel: 5, zoomLevel: 5,
size: .init(width: 300, height: 200), size: .init(width: 300, height: 200),
@@ -48,7 +48,7 @@ final class MapTilerURLBuilderTests: XCTestCase {
} }
func testDynamicMapBuilder() { func testDynamicMapBuilder() {
let url = builder.dynamicMapURL(for: .dark) let url = builder.interactiveMapURL(for: .dark)
let expectedURL: URL = "http://www.foo.com/dea61faf-292b-4774-9660-58fcef89a7f3/style.json?key=some_key" let expectedURL: URL = "http://www.foo.com/dea61faf-292b-4774-9660-58fcef89a7f3/style.json?key=some_key"
XCTAssertEqual(url, expectedURL) XCTAssertEqual(url, expectedURL)
} }
@@ -62,14 +62,14 @@ final class MapTilerURLBuilderTests: XCTestCase {
builder = configuration builder = configuration
let staticMapURL = builder.staticMapURL(for: .dark, let staticMapURL = builder.staticMapTileImageURL(for: .dark,
coordinates: .init(latitude: 1, longitude: 2), coordinates: .init(latitude: 1, longitude: 2),
zoomLevel: 5, zoomLevel: 5,
size: .init(width: 300, height: 200), size: .init(width: 300, height: 200),
attribution: .topLeft) attribution: .topLeft)
XCTAssertNil(staticMapURL) XCTAssertNil(staticMapURL)
let dynamicMapURL = builder.dynamicMapURL(for: .light) let dynamicMapURL = builder.interactiveMapURL(for: .light)
XCTAssertNil(dynamicMapURL) XCTAssertNil(dynamicMapURL)
} }
} }