Reputation: 387
I have an app with UIKit maps that I would like to update to the new SwiftUI map logic released in iOS 17. My UIKit logic has a segmented picker allowing selection of three different map styles: standard, hybrid, and imagery. I am having trouble in iOS 17 passing the MapStyle from the segmented picker to the map view.
I am seeing the following two compile errors associated with the picker:
Generic struct 'Picker' requires that 'MapStyle' conform to 'Hashable
Instance method 'tag' requires that 'MapStyle' conform to 'Hashable'
I ran across online a suggestion to place picker options within an enum conforming to CaseIterable and Identifiable. Swift automatically makes the enum conform to Equatable and Hashable by doing this.
enum Styles: MapStyle, Identifiable {
case standard
case hybrid
case imagery
var id: Styles { self }
}
But this results in different errors:
'Styles' declares raw type 'MapStyle', but does not conform to RawRepresentable and conformance could not be synthesized.
Cannot convert value of type 'Styles' to expected argument type 'MapStyle'
So I might have a hashable parameter, but mapStyle() may not have it in a usable form.
Any ideas how to resolve this is much appreciated.
struct DetailView: View {
var item: TravelEntries // coreData
@State private var mapStyle: MapStyle = .standard
var coordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(
latitude: item.entryLat,
longitude: item.entryLong)
}
var body: some View {
VStack {
Map() {
Marker(item.entryCatName ?? "", coordinate: coordinate)
.tint(.red)
}
.mapStyle(mapStyle)
Picker("", selection: $mapStyle) {
Text("Default").tag(MapStyle.standard)
Text("Transit").tag(MapStyle.hybrid)
Text("Satellite").tag(MapStyle.imagery)
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
Upvotes: 1
Views: 790
Reputation: 36782
You could try using this simple approach, where you calculate the var selectedMapStyle: MapStyle
based
on the Picker
integer selection.
struct ContentView: View {
@State private var mapType: Int = 0
var coordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: 35.685, longitude: 139.7514)
}
var selectedMapStyle: MapStyle {
return switch(mapType) {
case 0: .standard
case 1: .hybrid
case 2: .imagery
default: .standard
}
}
var body: some View {
VStack {
Map {
Marker("item name", coordinate: coordinate)
.tint(.red)
}
.mapStyle(selectedMapStyle)
Picker("", selection: $mapType) {
Text("Default").tag(0)
Text("Transit").tag(1)
Text("Satellite").tag(2)
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
Upvotes: 6