1
1
import ArcGIS
2
2
import Foundation
3
3
import Flutter
4
+ import SwiftUI
5
+
4
6
5
7
class ArcgisMapView : NSObject , FlutterPlatformView {
6
8
7
- private let defaultGraphicsOverlay = AGSGraphicsOverlay ( )
9
+ private let defaultGraphicsOverlay = GraphicsOverlay ( )
8
10
9
11
private let methodChannel : FlutterMethodChannel
10
12
private let zoomEventChannel : FlutterEventChannel
@@ -20,22 +22,23 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
20
22
21
23
private let initialZoom : Int
22
24
23
- private var mapView : AGSMapView
24
- private let map = AGSMap ( )
25
- private let graphicsOverlay = AGSGraphicsOverlay ( )
26
- private let userIndicatorGraphic = AGSGraphic ( )
27
- private let pinGraphic = AGSGraphic ( )
28
- private let routeLineGraphic = AGSGraphic ( )
25
+ private var mapView : MapView
26
+ private let map = Map ( )
27
+ private let graphicsOverlay = GraphicsOverlay ( )
28
+ private let userIndicatorGraphic = Graphic ( )
29
+ private let pinGraphic = Graphic ( )
30
+ private let routeLineGraphic = Graphic ( )
29
31
30
- private var routeLineGraphics = [ AGSGraphic ] ( )
32
+ private var routeLineGraphics = [ Graphic ] ( )
31
33
32
- private var routePoints = Array < AGSPoint > ( )
34
+ private var routePoints = Array < Point > ( )
33
35
34
36
35
37
private static let defaultDuration = 0.8
36
-
38
+
39
+ private var hostingController : UIHostingController < MapView >
37
40
func view( ) -> UIView {
38
- return mapView
41
+ return hostingController . view
39
42
}
40
43
41
44
init (
@@ -61,73 +64,65 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
61
64
centerPositionEventChannel. setStreamHandler ( centerPositionStreamHandler)
62
65
63
66
if let apiKey = mapOptions. apiKey {
64
- AGSArcGISRuntimeEnvironment . apiKey = apiKey
67
+ ArcGISEnvironment . apiKey = APIKey ( apiKey)
65
68
}
66
69
if let licenseKey = mapOptions. licenseKey {
67
70
do {
68
- try AGSArcGISRuntimeEnvironment . setLicenseKey ( licenseKey)
71
+ try ArcGISEnvironment . setLicense ( with : LicenseKey ( licenseKey) ! )
69
72
} catch {
70
73
print ( " setLicenseKey failed. \( error) " )
71
74
}
72
75
}
73
76
74
77
initialZoom = Int ( mapOptions. zoom)
78
+
79
+ let viewpoint = Viewpoint (
80
+ latitude: mapOptions. initialCenter. latitude,
81
+ longitude: mapOptions. initialCenter. longitude,
82
+ scale: convertZoomLevelToMapScale ( Int ( mapOptions. zoom) )
83
+ )
75
84
76
- mapView = AGSMapView . init ( frame : frame )
85
+ mapView = MapView . init ( map : map , viewpoint : viewpoint , graphicsOverlays : [ defaultGraphicsOverlay ] , )
77
86
87
+ // Embed the SwiftUI MapView into a UIHostingController
88
+ hostingController = UIHostingController ( rootView: mapView)
89
+ hostingController. view. frame = frame
90
+ hostingController. view. backgroundColor = . clear
91
+
78
92
super. init ( )
79
93
80
94
if let isAttributionTextVisible = mapOptions. isAttributionTextVisible {
81
- mapView. isAttributionTextVisible = isAttributionTextVisible
95
+ mapView. attributionBarHidden ( ! isAttributionTextVisible)
82
96
}
83
97
84
98
if mapOptions. basemap != nil {
85
- map. basemap = AGSBasemap ( style: parseBaseMapStyle ( mapOptions. basemap!) )
99
+ map. basemap = Basemap ( style: parseBaseMapStyle ( mapOptions. basemap!) )
86
100
} else {
87
101
let layers = mapOptions. vectorTilesUrls!. map { url in
88
- AGSArcGISVectorTiledLayer ( url: URL ( string: url) !)
102
+ ArcGISVectorTiledLayer ( url: URL ( string: url) !)
89
103
}
90
- map. basemap = AGSBasemap ( baseLayers: layers, referenceLayers : nil )
104
+ map. basemap = Basemap ( baseLayers: layers)
91
105
}
92
106
93
107
map. minScale = convertZoomLevelToMapScale ( mapOptions. minZoom)
94
108
map. maxScale = convertZoomLevelToMapScale ( mapOptions. maxZoom)
95
109
96
- mapView. map = map
97
- mapView. graphicsOverlays. add ( defaultGraphicsOverlay)
98
-
99
- mapScaleObservation = mapView. observe ( \. mapScale) { [ weak self] ( map, notifier) in
100
- DispatchQueue . main. async {
101
- guard let self = self else {
102
- return
103
- }
104
- let newZoom = self . convertScaleToZoomLevel ( self . mapView. mapScale)
105
- self . zoomStreamHandler. addZoom ( zoom: newZoom)
106
- }
110
+ mapView. onScaleChanged { [ weak self] scale in
111
+ guard let self = self else { return }
112
+ let newZoom = self . convertScaleToZoomLevel ( scale)
113
+ self . zoomStreamHandler. addZoom ( zoom: newZoom)
107
114
}
108
- mapVisibleAreaObservation = mapView. observe ( \. visibleArea) { [ weak self] ( map, notifier) in
109
- DispatchQueue . main. async {
110
- guard let self = self else {
111
- return
112
- }
113
- guard let center = self . mapView. visibleArea? . extent. center else {
114
- return
115
- }
116
- guard let wgs84Center = AGSGeometryEngine . projectGeometry ( center, to: . wgs84( ) ) as? AGSPoint else { return }
115
+ mapView. onVisibleAreaChanged { [ weak self] polygon in
116
+ guard let self = self else { return }
117
+ let center = polygon. extent. center
118
+ if let wgs84Center = GeometryEngine . project ( center, into: . wgs84) as? Point {
117
119
self . centerPositionStreamHandler. add ( center: LatLng ( latitude: wgs84Center. y, longitude: wgs84Center. x) )
118
120
}
119
121
}
120
122
121
-
122
- let viewpoint = AGSViewpoint (
123
- latitude: mapOptions. initialCenter. latitude,
124
- longitude: mapOptions. initialCenter. longitude,
125
- scale: convertZoomLevelToMapScale ( Int ( mapOptions. zoom) )
126
- )
127
- mapView. setViewpoint ( viewpoint)
128
-
129
123
setMapInteractive ( mapOptions. isInteractive)
130
124
setupMethodChannel ( )
125
+
131
126
132
127
mapLoadStatusObservation = map. observe ( \. loadStatus, options: . initial) { [ weak self] ( map, notifier) in
133
128
DispatchQueue . main. async {
@@ -186,10 +181,11 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
186
181
result ( FlutterError ( code: " missing_data " , message: " lodFactor not provided " , details: nil ) )
187
182
return
188
183
}
189
-
190
- let currentZoomLevel = convertScaleToZoomLevel ( mapView . mapScale )
184
+
185
+ let currentZoomLevel = convertScaleToZoomLevel ( currentScale )
191
186
let totalZoomLevel = currentZoomLevel + lodFactor
192
187
if ( totalZoomLevel > convertScaleToZoomLevel ( map. maxScale) ) {
188
+ result ( true )
193
189
return
194
190
}
195
191
let newScale = convertZoomLevelToMapScale ( totalZoomLevel)
@@ -217,6 +213,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
217
213
let currentZoomLevel = convertScaleToZoomLevel ( mapView. mapScale)
218
214
let totalZoomLevel = currentZoomLevel - lodFactor
219
215
if ( totalZoomLevel < convertScaleToZoomLevel ( map. minScale) ) {
216
+ result ( true )
220
217
return
221
218
}
222
219
let newScale = convertZoomLevelToMapScale ( totalZoomLevel)
@@ -245,12 +242,12 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
245
242
do {
246
243
let padding : ViewPadding = try JsonUtil . objectOfJson ( args)
247
244
248
- mapView. contentInset = UIEdgeInsets (
245
+ mapView. contentInsets ( EdgeInsets (
249
246
top: padding. top,
250
- left : padding. left,
247
+ leading : padding. left,
251
248
bottom: padding. bottom,
252
- right : padding. right
253
- )
249
+ trailing : padding. right
250
+ ) )
254
251
255
252
result ( true )
256
253
} catch {
@@ -278,7 +275,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
278
275
}
279
276
280
277
mapView. setViewpoint (
281
- AGSViewpoint ( center: point. toAGSPoint ( ) , scale: scale) ,
278
+ Viewpoint ( center: point. toAGSPoint ( ) , scale: scale) ,
282
279
duration: ( animationOptions? . duration ?? 0 ) / 1000 ,
283
280
curve: animationOptions? . arcgisAnimationCurve ( ) ?? . linear
284
281
) { success in
@@ -297,7 +294,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
297
294
298
295
do {
299
296
let payload : MoveToPointsPayload = try JsonUtil . objectOfJson ( args)
300
- let polyline = AGSPolyline ( points: payload. points. map { latLng in AGSPoint ( x: latLng. longitude, y: latLng. latitude, spatialReference: . wgs84( ) ) } )
297
+ let polyline = Polyline ( points: payload. points. map { latLng in Point ( x: latLng. longitude, y: latLng. latitude, spatialReference: . wgs84) } )
301
298
302
299
if ( payload. padding != nil ) {
303
300
mapView. setViewpointGeometry ( polyline. extent, padding: payload. padding!) { success in
@@ -315,7 +312,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
315
312
316
313
private func onAddGraphic( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
317
314
let parser = GraphicsParser ( registrar: flutterPluginRegistrar)
318
- var newGraphics = [ AGSGraphic ] ( )
315
+ var newGraphics = [ Graphic ] ( )
319
316
do {
320
317
newGraphics. append ( contentsOf: try parser. parse ( dictionary: call. arguments as! Dictionary < String , Any > ) )
321
318
} catch {
@@ -325,7 +322,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
325
322
326
323
327
324
let existingIds = defaultGraphicsOverlay. graphics. compactMap { object in
328
- let graphic = object as! AGSGraphic
325
+ let graphic = object as! Graphic
329
326
return graphic. attributes [ " id " ] as? String
330
327
}
331
328
@@ -359,13 +356,13 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
359
356
}
360
357
361
358
let newGraphics = defaultGraphicsOverlay. graphics. filter ( { element in
362
- let graphic = element as! AGSGraphic
359
+ let graphic = element as! Graphic
363
360
let id = graphic. attributes [ " id " ] as? String
364
361
return id != graphicId
365
362
} )
366
363
367
- defaultGraphicsOverlay. graphics . removeAllObjects ( )
368
- defaultGraphicsOverlay. graphics . addObjects ( from : newGraphics)
364
+ defaultGraphicsOverlay. removeAllGraphics ( )
365
+ defaultGraphicsOverlay. addGraphics ( newGraphics)
369
366
370
367
result ( true )
371
368
}
@@ -376,7 +373,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
376
373
return
377
374
}
378
375
379
- map. basemap = AGSBasemap ( style: parseBaseMapStyle ( baseMapString) )
376
+ map. basemap = Basemap ( style: parseBaseMapStyle ( baseMapString) )
380
377
381
378
result ( true )
382
379
}
@@ -386,7 +383,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
386
383
result ( true )
387
384
}
388
385
389
- private func notifyStatus( _ status: AGSLoadStatus ) {
386
+ private func notifyStatus( _ status: LoadStatus ) {
390
387
methodChannel. invokeMethod ( " onStatusChanged " , arguments: status. jsonValue ( ) )
391
388
}
392
389
@@ -414,8 +411,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
414
411
// don't set "isMagnifierEnabled" since we don't want to use this feature
415
412
}
416
413
417
- private func parseBaseMapStyle( _ string: String ) -> AGSBasemapStyle {
418
- let baseMapStyle = AGSBasemapStyle . allCases. first { enumValue in
414
+ private func parseBaseMapStyle( _ string: String ) -> Basemap . Style {
415
+ let baseMapStyle = Basemap . allCases. first { enumValue in
419
416
enumValue. getJsonValue ( ) == string
420
417
}
421
418
if baseMapStyle == nil {
@@ -588,7 +585,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
588
585
}
589
586
}
590
587
591
- private func operationWithSymbol( _ call: FlutterMethodCall , _ result: @escaping FlutterResult , handler: ( AGSSymbol ) -> Void ) {
588
+ private func operationWithSymbol( _ call: FlutterMethodCall , _ result: @escaping FlutterResult , handler: ( Symbol ) -> Void ) {
592
589
do {
593
590
guard let args = call. arguments as? [ String : Any ] else {
594
591
result ( FlutterError ( code: " missing_data " , message: " Invalid arguments " , details: nil ) )
@@ -604,8 +601,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
604
601
}
605
602
}
606
603
607
- extension AGSBasemapStyle : CaseIterable {
608
- public static var allCases : [ AGSBasemapStyle ] {
604
+ extension Basemap . Style : CaseIterable {
605
+ public static var allCases : [ Basemap . Style ] {
609
606
[
610
607
. arcGISImagery,
611
608
. arcGISImageryStandard,
@@ -657,7 +654,7 @@ extension AGSBasemapStyle: CaseIterable {
657
654
}
658
655
}
659
656
660
- extension AGSBasemapStyle {
657
+ extension Basemap . Style {
661
658
func getJsonValue( ) -> String ? {
662
659
switch self {
663
660
case . arcGISImagery:
@@ -763,27 +760,25 @@ struct MoveToPointsPayload : Codable {
763
760
let padding : Double ?
764
761
}
765
762
766
- extension AGSLoadStatus {
763
+ extension LoadStatus {
767
764
func jsonValue( ) -> String {
768
765
switch self {
769
766
case . loaded:
770
767
return " loaded "
771
768
case . loading:
772
769
return " loading "
773
- case . failedToLoad :
774
- return " failedToLoad "
770
+ case . failed :
771
+ return " failed "
775
772
case . notLoaded:
776
773
return " notLoaded "
777
- case . unknown:
778
- return " unknown "
779
774
@unknown default :
780
775
return " unknown "
781
776
}
782
777
}
783
778
}
784
779
785
780
extension String {
786
- func autoPanModeFromString( ) -> AGSLocationDisplayAutoPanMode ? {
781
+ func autoPanModeFromString( ) -> LocationDisplay . AutoPanMode ? {
787
782
switch self {
788
783
case " compassNavigation " :
789
784
return . compassNavigation
@@ -799,7 +794,7 @@ extension String {
799
794
}
800
795
}
801
796
802
- extension AGSLocationDisplayAutoPanMode {
797
+ extension LocationDisplay . AutoPanMode {
803
798
func toName( ) -> String ? {
804
799
switch self {
805
800
case . off:
0 commit comments