@@ -616,16 +616,50 @@ class ArcgisMapView: NSObject, FlutterPlatformView {
616616 }
617617 }
618618
619+ /// Cleans up Flutter channels and view model references.
620+ ///
621+ /// ## Threading Considerations
622+ ///
623+ /// Flutter channel operations (`setStreamHandler`, `setMethodCallHandler`) **must** be called
624+ /// on the main thread. However, `deinit` can be triggered from a background thread when:
625+ ///
626+ /// 1. An async `Task` (e.g., in `onStartLocationDisplayDataSource`) captures `[weak self]`
627+ /// 2. The Task completes on a background thread (Swift's default async executor)
628+ /// 3. If `self` has no other strong references, ARC deallocates it on that background thread
629+ /// 4. This calls `deinit` on the background thread
630+ ///
631+ /// If we call `setStreamHandler(nil)` from a background thread, Flutter's
632+ /// `PlatformMessageHandlerIos::SetMessageHandler` detects the thread violation and
633+ /// crashes via `fml::KillProcess()`.
634+ ///
635+ /// ## Solution
636+ ///
637+ /// We check the current thread and dispatch to main if necessary. Channel references
638+ /// are captured locally since `self` properties become inaccessible during `deinit`.
619639 deinit {
620640 mapContentView. viewModel. onScaleChanged = nil
621641 mapContentView. viewModel. onVisibleAreaChanged = nil
622642 mapContentView. viewModel. onLoadStatusChanged = nil
623643 mapContentView. viewModel. onViewInit = nil
624644 mapContentView. viewModel. mapViewProxy = nil
625645
626- zoomEventChannel. setStreamHandler ( nil )
627- centerPositionEventChannel. setStreamHandler ( nil )
628- methodChannel. setMethodCallHandler ( nil )
646+ // Capture channel references locally - self.* properties are inaccessible
647+ // after deinit begins, and we need them for the potential async dispatch.
648+ let zoomChannel = zoomEventChannel
649+ let centerChannel = centerPositionEventChannel
650+ let methodChan = methodChannel
651+
652+ if Thread . isMainThread {
653+ zoomChannel. setStreamHandler ( nil )
654+ centerChannel. setStreamHandler ( nil )
655+ methodChan. setMethodCallHandler ( nil )
656+ } else {
657+ DispatchQueue . main. async {
658+ zoomChannel. setStreamHandler ( nil )
659+ centerChannel. setStreamHandler ( nil )
660+ methodChan. setMethodCallHandler ( nil )
661+ }
662+ }
629663 }
630664}
631665
@@ -819,7 +853,6 @@ extension Basemap.Style {
819853 return " osmNavigation "
820854 case . osmNavigationDark:
821855 return " osmNavigationDark "
822-
823856 }
824857 }
825858}
0 commit comments