Skip to content

Commit 9fde28d

Browse files
authored
Merge pull request #472 from Esri/Caleb/Fix-ShowGridSettings
[Fix] `Show grid` grid settings
2 parents 4e841ac + 3666653 commit 9fde28d

File tree

1 file changed

+108
-132
lines changed

1 file changed

+108
-132
lines changed

Shared/Samples/Show grid/ShowGridView.swift

Lines changed: 108 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,23 @@ import ArcGIS
1616
import SwiftUI
1717

1818
struct ShowGridView: View {
19-
/// A map with topographic basemap.
20-
@State private var map: Map = {
21-
let map = Map(basemapStyle: .arcGISTopographic)
22-
map.initialViewpoint = Viewpoint(latitude: 34.05, longitude: -118.25, scale: 8e6)
23-
return map
24-
}()
25-
26-
/// The map view's grid, initially set to a Lat-Lon grid.
27-
@State private var grid: ArcGIS.Grid = LatitudeLongitudeGrid()
19+
/// The view model for the sample.
20+
@StateObject private var model = Model()
2821

2922
/// A Boolean value indicating whether the settings view should be presented.
3023
@State private var showsGridSettingsView = false
3124

3225
var body: some View {
33-
MapView(map: map)
34-
.grid(grid)
26+
MapView(map: model.map)
27+
.grid(model.grid)
3528
.toolbar {
3629
ToolbarItem(placement: .bottomBar) {
3730
Button("Grid Settings") {
3831
showsGridSettingsView = true
3932
}
4033
.popover(isPresented: $showsGridSettingsView) {
4134
NavigationStack {
42-
GridSettingsView(grid: $grid)
35+
GridSettingsView(model: model)
4336
}
4437
.presentationDetents([.fraction(0.6), .large])
4538
.frame(idealWidth: 350, idealHeight: 480)
@@ -49,113 +42,127 @@ struct ShowGridView: View {
4942
}
5043
}
5144

52-
// MARK: - Settings View
53-
5445
private extension ShowGridView {
55-
struct GridSettingsView: View {
56-
/// The action to dismiss the sheet.
57-
@Environment(\.dismiss) private var dismiss
58-
59-
/// The binding to the grid object.
60-
@Binding var grid: ArcGIS.Grid
61-
62-
/// A Boolean value indicating whether the grid is visible.
63-
@State private var gridIsVisible = true
64-
65-
/// A Boolean value indicating whether the grid labels are visible.
66-
@State private var labelsAreVisible = true
67-
68-
/// The color of the grid lines.
69-
@State private var gridColor = Color(uiColor: .red)
70-
71-
/// The color of the grid labels.
72-
@State private var labelsColor = Color(uiColor: .red)
46+
// MARK: - Model
47+
48+
/// The view model for the sample.
49+
final class Model: ObservableObject {
50+
/// A map with topographic basemap.
51+
let map: Map = {
52+
let map = Map(basemapStyle: .arcGISTopographic)
53+
map.initialViewpoint = Viewpoint(latitude: 34.05, longitude: -118.25, scale: 8e6)
54+
return map
55+
}()
7356

74-
/// The kind of grid to display
75-
@State private var gridType: GridType = .latitudeLongitude
57+
/// The map view's grid, initially set to a Lat-Lon grid.
58+
@Published var grid: ArcGIS.Grid = LatitudeLongitudeGrid()
7659

77-
/// The positioning of the grid's labels.
78-
@State private var labelPosition: ArcGIS.Grid.LabelPosition = .allSides
60+
/// The kind of grid to display.
61+
@Published var gridType: GridType = .latitudeLongitude {
62+
didSet { grid = makeGrid(type: gridType) }
63+
}
7964

8065
/// The format used for labeling the grid.
81-
@State private var labelFormat: LatitudeLongitudeGrid.LabelFormat = .decimalDegrees
66+
@Published var labelFormat: LatitudeLongitudeGrid.LabelFormat = .decimalDegrees
8267

8368
/// The units used for labeling the USNG grid.
84-
@State private var usngLabelUnit: USNGGrid.LabelUnit = .kilometersMeters
69+
@Published var usngLabelUnit: USNGGrid.LabelUnit = .kilometersMeters
8570

8671
/// The units used for labeling the MGRS grid.
87-
@State private var mgrsLabelUnit: MGRSGrid.LabelUnit = .kilometersMeters
72+
@Published var mgrsLabelUnit: MGRSGrid.LabelUnit = .kilometersMeters
73+
74+
/// Creates a new grid of a given type.
75+
/// - Parameter gridType: The kind of grid to make.
76+
/// - Returns: A new `Grid` object.
77+
private func makeGrid(type gridType: GridType) -> ArcGIS.Grid {
78+
let newGrid: ArcGIS.Grid
79+
switch gridType {
80+
case .latitudeLongitude:
81+
let latitudeLongitudeGrid = LatitudeLongitudeGrid()
82+
latitudeLongitudeGrid.labelFormat = labelFormat
83+
newGrid = latitudeLongitudeGrid
84+
case .mgrs:
85+
let mgrsGrid = MGRSGrid()
86+
mgrsGrid.labelUnit = mgrsLabelUnit
87+
newGrid = mgrsGrid
88+
case .usng:
89+
let usngGrid = USNGGrid()
90+
usngGrid.labelUnit = usngLabelUnit
91+
newGrid = usngGrid
92+
case .utm:
93+
newGrid = UTMGrid()
94+
}
95+
96+
newGrid.isVisible = grid.isVisible
97+
newGrid.labelsAreVisible = grid.labelsAreVisible
98+
newGrid.linesColor = grid.linesColor
99+
newGrid.labelsColor = grid.labelsColor
100+
newGrid.labelPosition = grid.labelPosition
101+
102+
return newGrid
103+
}
104+
}
105+
106+
// MARK: - Settings View
107+
108+
struct GridSettingsView: View {
109+
/// The action to dismiss the sheet.
110+
@Environment(\.dismiss) private var dismiss
111+
112+
/// The view model for the sample.
113+
@ObservedObject var model: Model
88114

89115
var body: some View {
90116
Form {
91117
Section("Grid Line Settings") {
92-
Picker("Grid Type", selection: $gridType) {
118+
Picker("Grid Type", selection: $model.gridType) {
93119
ForEach(GridType.allCases, id: \.self) { type in
94120
Text(type.label)
95121
}
96122
}
97-
.onChange(of: gridType) { _ in
98-
grid = gridType.makeGrid()
99-
updateUI()
100-
}
101123

102-
Toggle("Visible", isOn: $gridIsVisible)
103-
.onChange(of: gridIsVisible) { _ in
104-
grid.isVisible = gridIsVisible
105-
}
124+
Toggle("Visible", isOn: $model.grid.isVisible)
106125

107-
ColorPicker("Color", selection: $gridColor)
108-
.onChange(of: gridColor) { _ in
109-
changeGridColor(to: UIColor(gridColor))
110-
}
126+
ColorPicker("Color", selection: $model.grid.linesColor)
111127
}
112128

113129
Section("Labels Settings") {
114-
Toggle("Visible", isOn: $labelsAreVisible)
115-
.onChange(of: labelsAreVisible) { _ in
116-
grid.labelsAreVisible = labelsAreVisible
117-
}
130+
Toggle("Visible", isOn: $model.grid.labelsAreVisible)
118131

119-
ColorPicker("Color", selection: $labelsColor)
120-
.onChange(of: labelsColor) { _ in
121-
changeLabelColor(to: UIColor(labelsColor))
122-
}
132+
ColorPicker("Color", selection: $model.grid.labelsColor)
123133

124-
Picker("Position", selection: $labelPosition) {
134+
Picker("Position", selection: $model.grid.labelPosition) {
125135
ForEach(Grid.LabelPosition.allCases, id: \.self) { position in
126136
Text(position.label)
127137
}
128138
}
129-
.onChange(of: labelPosition) { _ in
130-
grid.labelPosition = labelPosition
131-
}
132139

133-
if let latitudeLongitudeGrid = grid as? LatitudeLongitudeGrid {
134-
Picker("Format", selection: $labelFormat) {
140+
if let latitudeLongitudeGrid = model.grid as? LatitudeLongitudeGrid {
141+
Picker("Format", selection: $model.labelFormat) {
135142
ForEach(LatitudeLongitudeGrid.LabelFormat.allCases, id: \.self) { format in
136143
Text(format.label)
137144
}
138145
}
139-
.onChange(of: labelFormat) { _ in
140-
latitudeLongitudeGrid.labelFormat = labelFormat
146+
.onChange(of: model.labelFormat) { newLabelFormat in
147+
latitudeLongitudeGrid.labelFormat = newLabelFormat
141148
}
142-
} else if let mgrsGrid = grid as? MGRSGrid {
143-
Picker("Unit", selection: $mgrsLabelUnit) {
149+
} else if let mgrsGrid = model.grid as? MGRSGrid {
150+
Picker("Unit", selection: $model.mgrsLabelUnit) {
144151
ForEach(MGRSGrid.LabelUnit.allCases, id: \.self) { unit in
145152
Text(unit.label)
146153
}
147154
}
148-
.onChange(of: mgrsLabelUnit) { _ in
149-
mgrsGrid.labelUnit = mgrsLabelUnit
155+
.onChange(of: model.mgrsLabelUnit) { newMGRSLabelUnit in
156+
mgrsGrid.labelUnit = newMGRSLabelUnit
150157
}
151-
} else if let usngGrid = grid as? USNGGrid {
152-
Picker("Unit", selection: $usngLabelUnit) {
158+
} else if let usngGrid = model.grid as? USNGGrid {
159+
Picker("Unit", selection: $model.usngLabelUnit) {
153160
ForEach(USNGGrid.LabelUnit.allCases, id: \.self) { unit in
154161
Text(unit.label)
155162
}
156163
}
157-
.onChange(of: usngLabelUnit) { _ in
158-
usngGrid.labelUnit = usngLabelUnit
164+
.onChange(of: model.usngLabelUnit) { newUSNGLabelUnit in
165+
usngGrid.labelUnit = newUSNGLabelUnit
159166
}
160167
}
161168
}
@@ -167,69 +174,47 @@ private extension ShowGridView {
167174
Button("Done") { dismiss() }
168175
}
169176
}
170-
.onAppear {
171-
updateUI()
172-
}
173177
}
174-
175-
/// Update states and UI based on grid properties.
176-
private func updateUI() {
177-
gridIsVisible = grid.isVisible
178-
if let lineSymbolColor = (grid.lineSymbols.first { $0 is LineSymbol } as? LineSymbol)?.color {
179-
gridColor = Color(uiColor: lineSymbolColor)
180-
}
181-
gridType = GridType(grid: grid)!
182-
labelsAreVisible = grid.labelsAreVisible
183-
if let textSymbolColor = (grid.textSymbols.first { $0 is TextSymbol } as? TextSymbol)?.color {
184-
labelsColor = Color(uiColor: textSymbolColor)
185-
}
186-
labelPosition = grid.labelPosition
187-
if grid is LatitudeLongitudeGrid {
188-
labelFormat = (grid as! LatitudeLongitudeGrid).labelFormat
189-
} else if grid is MGRSGrid {
190-
mgrsLabelUnit = (grid as! MGRSGrid).labelUnit
191-
} else if grid is USNGGrid {
192-
usngLabelUnit = (grid as! USNGGrid).labelUnit
193-
}
178+
}
179+
}
180+
181+
// MARK: - Helper Extensions
182+
183+
private extension ArcGIS.Grid {
184+
/// The color of the grid lines.
185+
var linesColor: Color {
186+
get {
187+
let lineSymbol = lineSymbols.first(where: { $0 is LineSymbol }) as! LineSymbol
188+
return Color(uiColor: lineSymbol.color)
194189
}
195-
196-
/// Changes the grid line color.
197-
/// - Parameter color: The color for the grid lines.
198-
private func changeGridColor(to color: UIColor) {
199-
for symbol in grid.lineSymbols where symbol is LineSymbol {
190+
set {
191+
for symbol in lineSymbols where symbol is LineSymbol {
200192
let lineSymbol = symbol as! LineSymbol
201-
lineSymbol.color = color
193+
lineSymbol.color = UIColor(newValue)
202194
}
203195
}
204-
205-
/// Changes the grid labels color.
206-
/// - Parameter color: The color for the text symbols.
207-
private func changeLabelColor(to color: UIColor) {
208-
for symbol in grid.textSymbols where symbol is TextSymbol {
196+
}
197+
198+
/// The color of the grid labels.
199+
var labelsColor: Color {
200+
get {
201+
let textSymbol = textSymbols.first(where: { $0 is TextSymbol }) as! TextSymbol
202+
return Color(uiColor: textSymbol.color)
203+
}
204+
set {
205+
for symbol in textSymbols where symbol is TextSymbol {
209206
let textSymbol = symbol as! TextSymbol
210-
textSymbol.color = color
207+
textSymbol.color = UIColor(newValue)
211208
}
212209
}
213210
}
214211
}
215212

216-
// MARK: - Helper Extensions
217-
218213
private extension ShowGridView {
219214
/// The kinds of grid to show in a map view.
220215
enum GridType: CaseIterable {
221216
case latitudeLongitude, mgrs, usng, utm
222217

223-
init?(grid: ArcGIS.Grid) {
224-
switch grid {
225-
case is LatitudeLongitudeGrid: self = .latitudeLongitude
226-
case is MGRSGrid: self = .mgrs
227-
case is USNGGrid: self = .usng
228-
case is UTMGrid: self = .utm
229-
default: fatalError("Unknown grid type")
230-
}
231-
}
232-
233218
var label: String {
234219
switch self {
235220
case .latitudeLongitude: "Latitude-Longitude"
@@ -238,15 +223,6 @@ private extension ShowGridView {
238223
case .utm: "UTM"
239224
}
240225
}
241-
242-
func makeGrid() -> ArcGIS.Grid {
243-
switch self {
244-
case .latitudeLongitude: LatitudeLongitudeGrid()
245-
case .mgrs: MGRSGrid()
246-
case .usng: USNGGrid()
247-
case .utm: UTMGrid()
248-
}
249-
}
250226
}
251227
}
252228

0 commit comments

Comments
 (0)