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

SwiftUI RasterSource doesn't allow expected use of `.scheme` property

Open stephent opened this issue 1 year ago • 0 comments

Environment

  • Xcode version: Version 16.0 (16A242d)
  • iOS version: 17.5.1
  • Devices affected: Any - it's a compilation issue
  • Maps SDK Version: 11.7.1

Observed behavior and steps to reproduce

Trying to set the .scheme property as normal gives a compiler error as shown:

CleanShot 2024-10-28 at 11 33 14@2x

As I workaround, I can do this instead:

import SwiftUI
import MapboxMaps
import DerivedStateProvider

import DesignSystem

struct WeatherMap: View {
	@Environment(WeatherModuleViewModel.self) var viewModel
	
	let source: RasterSource = {
		var source = RasterSource(id: "weather-test")
		source.scheme = .tms // workaround - set scheme property here 
		return source
	}()
	
	public init() {}
	
	var body: some View {
		
		@Bindable var module = viewModel.moduleState
		
		VStack {
			Map(initialViewport: .camera(center: self.viewModel.preset.primaryPin.coordinate, zoom: 6, bearing: 0, pitch: 0)) {
				
				if module.tileURLTemplate != nil {
					source
						.maxzoom(16)
						.minzoom(1)
						.tileNetworkRequestsDelay(200)
						.tiles([module.tileURLTemplate!])
						
					RasterLayer(id: "weather-test-layer", source: "weather-test")
						.rasterOpacity(0.8)
				}
			}.ignoresSafeArea()
		}
	}
}

Expected behavior

.scheme should be settable as expected inline as follows:

	RasterSource(id: "weather-test")
		.maxzoom(16)
		.minzoom(1)
		.tileNetworkRequestsDelay(200)
		.tiles([module.tileURLTemplate!])
		.scheme(.tms)

Notes / preliminary analysis

Unclear why this is different - the property appears to be declared in a similar fashion to the others, e.g.

/// A raster tile source.
///
/// - SeeAlso: [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#raster)
public struct RasterSource: Source {

    public let type: SourceType
    public let id: String

...

    /// Minimum zoom level for which tiles are available, as in the TileJSON spec.
    /// Default value: 0.
    public var minzoom: Double?

...

    /// Influences the y direction of the tile coordinates. The global-mercator (aka Spherical Mercator) profile is assumed.
    /// Default value: "xyz".
    public var scheme: Scheme?

...
}

Here's what Claude had to say:

Given what we discovered, it seems like there's a mismatch in how MapBox implemented their SwiftUI property wrappers. Let me break down what I think might be happening:

  • Most of the properties (like maxzoom, minzoom, etc.) are properly wrapped with SwiftUI property modifiers that create method-style chainable modifiers (that's why they work with the .maxzoom(16) syntax and show up in teal)
  • But scheme seems to have been missed in this wrapper layer (showing up in purple), suggesting it's being exposed directly as a Swift property rather than being wrapped in the SwiftUI modifier pattern

This is particularly evident because:

  • We couldn't use .scheme(.tms) like the other modifiers
  • We had to set it directly on the source instance
  • The direct property is marked as Scheme? in the header but the modifier system wasn't handling that optional type correctly

This kind of inconsistency often happens when building SwiftUI wrappers around existing UIKit/imperative APIs, especially if some properties are auto-generated or wrapped automatically while others need manual handling.

stephent avatar Oct 28 '24 17:10 stephent