@@ -110,8 +110,14 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
110110 }
111111
112112 private func setupMethodChannel( ) {
113- methodChannel. setMethodCallHandler ( { [ self ] ( call: FlutterMethodCall , result: @escaping FlutterResult ) -> Void in
114- switch ( call. method) {
113+ methodChannel. setMethodCallHandler ( {
114+ [ weak self] ( call: FlutterMethodCall , result: @escaping FlutterResult ) -> Void in
115+ guard let self = self else {
116+ result ( FlutterError ( code: " disposed " , message: " View was disposed " , details: nil ) )
117+ return
118+ }
119+
120+ switch call. method {
115121 case " on_init_complete " : waitForViewToInit ( call, result)
116122 case " zoom_in " : onZoomIn ( call, result)
117123 case " zoom_out " : onZoomOut ( call, result)
@@ -146,17 +152,18 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
146152
147153 private func waitForViewToInit( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
148154 if mapContentView. viewModel. mapViewProxy != nil {
149- result ( true )
155+ result ( true )
150156 } else {
151- mapContentView. viewModel. onViewInit = { [ weak self ] in
157+ mapContentView. viewModel. onViewInit = { [ weak vm = mapContentView . viewModel ] in
152158 result ( true )
159+ vm? . onViewInit = nil
153160 }
154161 }
155162 }
156163
157164 private func onZoomIn( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
158- let currentScale = mapContentView. viewModel. viewpoint. targetScale
159-
165+ let currentScale = mapContentView. viewModel. viewpoint. targetScale
166+
160167 guard let args = call. arguments as? [ String : Any ] else {
161168 result ( FlutterError ( code: " missing_data " , message: " Invalid arguments " , details: nil ) )
162169 return
@@ -176,9 +183,10 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
176183 }
177184 }
178185 let newScale = ArcgisMapView . convertZoomLevelToMapScale ( totalZoomLevel)
179- Task {
186+ Task { [ weak self] in
187+ guard let self = self else { return }
180188 do {
181- await mapContentView. viewModel. mapViewProxy? . setViewpointScale ( newScale)
189+ await self . mapContentView. viewModel. mapViewProxy? . setViewpointScale ( newScale)
182190 result ( true )
183191 }
184192 }
@@ -206,20 +214,23 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
206214 }
207215 }
208216 let newScale = ArcgisMapView . convertZoomLevelToMapScale ( totalZoomLevel)
209- Task {
217+ Task { [ weak self] in
218+ guard let self = self else { return }
210219 do {
211- let success = await mapContentView. viewModel. mapViewProxy? . setViewpointScale ( newScale)
220+ let success = await self . mapContentView. viewModel. mapViewProxy? . setViewpointScale (
221+ newScale)
212222 result ( success)
213223 }
214224 }
215225 }
216-
217- private func onRotate( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
226+
227+ private func onRotate( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
218228 guard let angleDouble = call. arguments as? Double else {
219229 result ( FlutterError ( code: " missing_data " , message: " Invalid arguments " , details: nil ) )
220230 return
221231 }
222- Task {
232+ Task { [ weak self] in
233+ guard let self = self else { return }
223234 do {
224235 let success = await mapContentView. viewModel. mapViewProxy? . setViewpointRotation ( angleDouble)
225236 result ( success)
@@ -254,7 +265,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
254265 result ( FlutterError ( code: " missing_data " , message: " Invalid arguments " , details: nil ) )
255266 return
256267 }
257- Task {
268+ Task { [ weak self] in
269+ guard let self = self else { return }
258270 do {
259271 let point : LatLng = try JsonUtil . objectOfJson ( args [ " point " ] as! Dictionary < String , Any > )
260272 let zoomLevel = args [ " zoomLevel " ] as? Int
@@ -266,9 +278,9 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
266278 if let zoomLevel = zoomLevel {
267279 scale = ArcgisMapView . convertZoomLevelToMapScale ( zoomLevel)
268280 } else {
269- scale = mapContentView. viewModel. viewpoint. targetScale
281+ scale = self . mapContentView. viewModel. viewpoint. targetScale
270282 }
271- let success = await mapContentView. viewModel. mapViewProxy? . setViewpoint (
283+ let success = await self . mapContentView. viewModel. mapViewProxy? . setViewpoint (
272284 Viewpoint ( center: point. toAGSPoint ( ) , scale: scale) ,
273285 duration: ( animationOptions? . duration ?? 0 ) / 1000
274286 )
@@ -287,9 +299,12 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
287299 Task {
288300 do {
289301 let payload : MoveToPointsPayload = try JsonUtil . objectOfJson ( args)
290- let polyline = Polyline ( points: payload. points. map { latLng in Point ( x: latLng. longitude, y: latLng. latitude, spatialReference: . wgs84) } )
291-
292- if ( payload. padding != nil ) {
302+ let polyline = Polyline (
303+ points: payload. points. map { latLng in
304+ Point ( x: latLng. longitude, y: latLng. latitude, spatialReference: . wgs84)
305+ } )
306+
307+ if payload. padding != nil {
293308 let success = try await mapContentView. viewModel. mapViewProxy!. setViewpointGeometry ( polyline. extent, padding: payload. padding!)
294309 result ( success)
295310 } else {
@@ -312,8 +327,9 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
312327 return
313328 }
314329
315-
316- let existingIds = mapContentView. viewModel. defaultGraphicsOverlay. graphics. compactMap { object in
330+
331+ let existingIds = mapContentView. viewModel. defaultGraphicsOverlay. graphics. compactMap {
332+ object in
317333 let graphic = object as! Graphic
318334 return graphic. attributes [ " id " ] as? String
319335 }
@@ -327,7 +343,7 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
327343 return existingIds. contains ( id)
328344 } )
329345
330- if ( hasExistingGraphics) {
346+ if hasExistingGraphics {
331347 result ( false )
332348 return
333349 }
@@ -370,7 +386,8 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
370386 }
371387
372388 private func onRetryLoad( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
373- Task {
389+ Task { [ weak self] in
390+ guard let self = self else { return }
374391 do {
375392 try await mapContentView. viewModel. map. retryLoad ( )
376393 result ( true )
@@ -430,9 +447,10 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
430447
431448
432449 private func onStartLocationDisplayDataSource( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
433- Task {
450+ Task { [ weak self] in
451+ guard let self = self else { return }
434452 do {
435- try await mapContentView. viewModel. locationDisplay. dataSource. start ( ) ;
453+ try await self . mapContentView. viewModel. locationDisplay. dataSource. start ( )
436454 result ( true )
437455 }
438456 catch {
@@ -447,9 +465,10 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
447465 }
448466
449467 private func onStopLocationDisplayDataSource( _ call: FlutterMethodCall , _ result: @escaping FlutterResult ) {
450- Task {
468+ Task { [ weak self] in
469+ guard let self = self else { return }
451470 do {
452- await mapContentView. viewModel. locationDisplay. dataSource. stop ( )
471+ await self . mapContentView. viewModel. locationDisplay. dataSource. stop ( )
453472 result ( true )
454473 }
455474 }
@@ -568,18 +587,19 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
568587 }
569588
570589 private func onExportImage( _ result: @escaping FlutterResult ) {
571- Task {
572- do {
573- let image = try await mapContentView. viewModel. mapViewProxy!. exportImage ( )
574- if let imageData = image. pngData ( ) {
575- result ( FlutterStandardTypedData ( bytes: imageData) )
576- } else {
577- result ( FlutterError ( code: " conversion_error " , message: " Failed to convert image to PNG data " , details: nil ) )
578- }
579- } catch {
580- result ( FlutterError ( code: " export_error " , message: error. localizedDescription, details: nil ) )
581- }
582- }
590+ Task { [ weak self] in
591+ guard let self = self else { return }
592+ do {
593+ let image = try await self . mapContentView. viewModel. mapViewProxy!. exportImage ( )
594+ if let imageData = image. pngData ( ) {
595+ result ( FlutterStandardTypedData ( bytes: imageData) )
596+ } else {
597+ result ( FlutterError ( code: " conversion_error " , message: " Failed to convert image to PNG data " , details: nil ) )
598+ }
599+ } catch {
600+ result ( FlutterError ( code: " export_error " , message: error. localizedDescription, details: nil ) )
601+ }
602+ }
583603 }
584604
585605 private func operationWithSymbol( _ call: FlutterMethodCall , _ result: @escaping FlutterResult , handler: ( Symbol ) -> Void ) {
@@ -591,11 +611,23 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
591611 let symbol = try GraphicsParser ( registrar: flutterPluginRegistrar) . parseSymbol ( args)
592612 handler ( symbol)
593613 result ( true )
594- }
595- catch {
614+ } catch {
596615 result ( FlutterError ( code: " unknown_error " , message: " Error while adding graphic. \( error) " , details: nil ) )
597616 }
598617 }
618+
619+ deinit {
620+ mapContentView. viewModel. onScaleChanged = nil
621+ mapContentView. viewModel. onVisibleAreaChanged = nil
622+ mapContentView. viewModel. onLoadStatusChanged = nil
623+ mapContentView. viewModel. onViewInit = nil
624+ mapContentView. viewModel. mapViewProxy = nil
625+ mapContentView. viewModel. stopLocationDataSource ( )
626+
627+ zoomEventChannel. setStreamHandler ( nil )
628+ centerPositionEventChannel. setStreamHandler ( nil )
629+ methodChannel. setMethodCallHandler ( nil )
630+ }
599631}
600632
601633extension Basemap . Style : CaseIterable {
@@ -788,18 +820,18 @@ extension Basemap.Style {
788820 return " osmNavigation "
789821 case . osmNavigationDark:
790822 return " osmNavigationDark "
791-
823+
792824 }
793825 }
794826}
795827
796- struct MoveToPointsPayload : Codable {
797- let points : [ LatLng ]
798- let padding : Double ?
828+ struct MoveToPointsPayload : Codable {
829+ let points : [ LatLng ]
830+ let padding : Double ?
799831}
800832
801833extension LoadStatus {
802- func jsonValue( ) -> String {
834+ func jsonValue( ) -> String {
803835 switch self {
804836 case . loaded:
805837 return " loaded "
@@ -818,16 +850,16 @@ extension LoadStatus {
818850extension String {
819851 func autoPanModeFromString( ) -> LocationDisplay . AutoPanMode ? {
820852 switch self {
821- case " compassNavigation " :
822- return . compassNavigation
823- case " navigation " :
824- return . navigation
825- case " recenter " :
826- return . recenter
827- case " off " :
828- return . off
829- default :
830- return nil
853+ case " compassNavigation " :
854+ return . compassNavigation
855+ case " navigation " :
856+ return . navigation
857+ case " recenter " :
858+ return . recenter
859+ case " off " :
860+ return . off
861+ default :
862+ return nil
831863 }
832864 }
833865}
0 commit comments