@@ -16,30 +16,23 @@ import ArcGIS
1616import SwiftUI
1717
1818struct 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-
5445private 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-
218213private 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