feat: remove deprecated RNMBXMapView's mapView & mapboxMap APIs
Description
In our App, the deprecated APIs (RNMBXMapView.mapView & RNMBXMapView.mapboxMap) cause the app to crash because rnmapbox is trying to unwrap them while they are still nil.
This PR removes those two deprecated APIs and changes all their usage to the safe withMapView & withMapboxMap API calls. After this fix our app no longer crashes.
Checklist
- [x] I've read
CONTRIBUTING.md - [x] I updated the doc/other generated code with running
yarn generatein the root folder - [ ] I have tested the new feature on
/exampleapp.- [ ] In V11 mode/ios
- [ ] In New Architecture mode/ios
- [] In V11 mode/android
- [] In New Architecture mode/android
- [x] I added/updated a sample - if a new feature was implemented (
/example)
Screenshot OR Video
Component to reproduce the issue you're fixing
Kinda hard since the crash is triggered by an edge case in our app and we don't know how to create a minimal reproducing example yet but after I patched this package our app no longer crashes.
@PRESIDENT810 thanks much for the PR
Unfortunately it's a bit complicated. Like in case of remove? withMapView could keep stuff alive and create a leak. So one thing we have to be carefully withMapView is leaks the other is concurrency, as the code will be called from other thread. And can cause deadlock and other issues.
Do you perhaps has stack traces? So we can address those cases, where you hit by the nil mapboxMap?
@mfazekas Here's the stacktrace
Crashed: com.apple.main-thread
0 <our app> 0x2591ccc closure #5 in RNMBXMapView.setupEvents() + 1117 (RNMBXMapView.swift:1117)
1 <our app> 0x258e554 specialized closure #1 in RNMBXMapView.onEvery<A>(event:handler:) + 305072
2 <our app> 0x2597c38 partial apply for specialized closure #1 in RNMBXMapView.onNext<A>(event:handler:) + 343700 (<compiler-generated>:343700)
3 MapboxMaps 0xb03cc closure #1 in MapboxObservable.onNext<A>(event:handler:) + 84
4 MapboxMaps 0xb1950 partial apply for closure #1 in MapboxObservable.onNext<A>(event:handler:) + 20 (<compiler-generated>:20)
5 MapboxMaps 0xb0524 @objc MapboxObservable.BlockObserver.notify(for:) + 166 (MapboxObservable.swift:166)
6 MapboxCoreMaps 0x297f4 mapbox::bindgen::mapbox::maps::Observer::notify(mapbox::maps::Event const&) + 52
7 MapboxCoreMaps 0x95644 mapbox::maps::ObserverWrapper::notify(mbgl::ObservableEvent const&) + 692
8 MapboxCoreMaps 0x560d18 std::__1::__function::__func<mbgl::Observable::dispatchEvent(mbgl::ObservableEvent const&, mbgl::DispatchMode)::$_0, std::__1::allocator<mbgl::Observable::dispatchEvent(mbgl::ObservableEvent const&, mbgl::DispatchMode)::$_0>, void ()>::operator()() + 156
9 MapboxCommon 0x4dc98 mapbox::common::platform::taskScope() + 1360
10 CoreFoundation 0xf92c __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 28
11 CoreFoundation 0xf744 __CFRunLoopDoSource0 + 172
12 CoreFoundation 0xf604 __CFRunLoopDoSources0 + 332
13 CoreFoundation 0xff20 __CFRunLoopRun + 840
14 CoreFoundation 0x11adc CFRunLoopRunSpecific + 572
15 GraphicsServices 0x1454 GSEventRunModal + 168
16 UIKitCore 0x135274 -[UIApplication _run] + 816
17 UIKitCore 0x100a28 UIApplicationMain + 336
18 <our app> 0xf9b4 main + 36 (main.m:36)
I can see the crash is caused by 5th closure in RNMBXMapView.setupEvents with "Swift runtime failure: Unexpectedly found nil while implicitly unwrapping an optional value" but I can't see what triggers it.
For leaks, I think I used [weak self] and tried my best to avoid circular reference here, and for concurrency, I think the callers to withMapView & withMapboxMap will not wait for anything. If RNMBXMapView._mapView is nil, then the closure is appended to waiters and the function returns immediately. It's basically promising to execute that closure as soon as _mapView is ready, and when it's ready, closures in waiter will execute serially, which I don't think would cause deadlocks.
ping @mfazekas We've been using this patch in prod for a several weeks with good results - would love if this could merge to main so that we don't have to maintain our own patch. assuming others would benefit from this as well; happy to make more improvements in the future
@PRESIDENT810 thanks again, and sorry for taking this long.
So generally there is 2 cases in the changes.
1.) Things like MapView.queryRenderedFeaturesInRect: withMapboxMap is good here, as we might have called queryRenderedFeaturesInRect before the map init has finished. Waiting for an underlying map view is great here.
2.) Components added to a specific map/style - I think they'd be better to store the map/style. I don't like withMapboxMap there as it might mean a different map/style we've already added the component.
@PRESIDENT810 thanks much for the PR
Unfortunately it's a bit complicated. Like in case of remove? withMapView could keep stuff alive and create a leak. So one thing we have to be carefully withMapView is leaks the other is concurrency, as the code will be called from other thread. And can cause deadlock and other issues.
Do you perhaps has stack traces? So we can address those cases, where you hit by the nil mapboxMap?
@mfazekas
I encountered the same issue. Below is the library version information,
"@rnmapbox/maps": "10.1.45",
"react": "18.3.1",
"react-native": "0.77.3",
Below is the stack trace captured by Firebase
Crashlytics - Stack trace
Platform: apple
Issue: fe3bc65935115ec9828d90410e1d4584
Session: 95f85b7fd0464ae6bb83bd846f315998_DNE_0_v2
Date: Thu Nov 06 2025 15:15:20 GMT+0800 (中国标准时间)
Crashed: com.apple.main-thread
0 testAppIot 0xcb3e28 closure #2 in RNMBXMapView.setupEvents() + 1107 (RNMBXMapView.swift:1107)
1 testAppIot 0xcb112c specialized closure #1 in RNMBXMapView.onEvery<A>(event:handler:) + 940568
2 testAppIot 0xcba6dc partial apply for specialized closure #1 in RNMBXMapView.onNext<A>(event:handler:) + 978888 (
com.apple.uikit.eventfetch-thread 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 Foundation 0xf79c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 8 Foundation 0x15020 -[NSRunLoop(NSRunLoop) runUntilDate:] + 64 9 UIKitCore 0x11f56c -[UIEventFetcher threadMain] + 424 10 Foundation 0x75804 NSThread__start + 732 11 libsystem_pthread.dylib 0x3344 _pthread_start + 136 12 libsystem_pthread.dylib 0xab8 thread_start + 8
com.google.firebase.crashlytics.MachExceptionServer 0 testAppIot 0x57d118 FIRCLSProcessRecordAllThreads + 392 (FIRCLSProcess.c:392) 1 testAppIot 0x57d4fc FIRCLSProcessRecordAllThreads + 423 (FIRCLSProcess.c:423) 2 testAppIot 0x57482c FIRCLSHandler + 34 (FIRCLSHandler.m:34) 3 testAppIot 0x577108 FIRCLSMachExceptionServer + 521 (FIRCLSMachException.c:521) 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.apple.NSURLConnectionLoader 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 CFNetwork 0xa030c +[__CFN_CoreSchedulingSetRunnable _run:] + 416 8 Foundation 0x75804 NSThread__start + 732 9 libsystem_pthread.dylib 0x3344 _pthread_start + 136 10 libsystem_pthread.dylib 0xab8 thread_start + 8
com.apple.CFSocket.private 0 libsystem_kernel.dylib 0x832c select$DARWIN_EXTSN + 8 1 libsystem_kernel.dylib 0x832c __select + 8 2 CoreFoundation 0x97a44 __CFSocketManager + 704 3 libsystem_pthread.dylib 0x3344 _pthread_start + 136 4 libsystem_pthread.dylib 0xab8 thread_start + 8
Thread 0 libsystem_kernel.dylib 0xa90 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0xa58 _pthread_wqthread + 368 2 libsystem_pthread.dylib 0xaac start_wqthread + 8
com.facebook.react.JavaScript 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 testAppIot 0x96bf38 +[RCTCxxBridge runRunLoop] + 347 (RCTCxxBridge.mm:347) 8 Foundation 0x75804 NSThread__start + 732 9 libsystem_pthread.dylib 0x3344 _pthread_start + 136 10 libsystem_pthread.dylib 0xab8 thread_start + 8
hades 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 hermes 0xcc7fc hermes::vm::HadesGC::Executor::worker() + 116 4 hermes 0xcc764 void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_deletestd::__1::__thread_struct>, hermes::vm::HadesGC::Executor::Executor()::'lambda'()>>(void*) + 44 5 libsystem_pthread.dylib 0x3344 _pthread_start + 136 6 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.Worker 1 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.Worker 2 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.Worker 3 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.Worker 4 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.location.sharedRunloop 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 CoreFoundation 0x8c674 CFRunLoopRun + 64 8 MapboxCommon 0xde3c0 mapbox::common::location::LocationServiceFactory::locationService() + 66872 9 Foundation 0x75804 NSThread__start + 732 10 libsystem_pthread.dylib 0x3344 _pthread_start + 136 11 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.AssetFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.TileStoreFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.LocalFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.OnlineFileSource 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x2135c std::__1::condition_variable::__do_timed_wait(std::__1::unique_lockstd::__1::mutex&, std::__1::chrono::time_point<std::__1::chrono::system_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l>>>) + 104 3 MapboxCommon 0x716c8 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1360 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
com.mapbox.common.ResourceLoaderThread 0 libsystem_kernel.dylib 0x6438 __psynch_cvwait + 8 1 libsystem_pthread.dylib 0x1e50 _pthread_cond_wait + 984 2 libc++.1.dylib 0x212c4 std::__1::condition_variable::wait(std::__1::unique_lockstd::__1::mutex&) + 32 3 MapboxCommon 0x71698 mapbox::common::ThreadedSchedulerBase::getDefaultPriority() + 1312 4 libsystem_pthread.dylib 0x3344 _pthread_start + 136 5 libsystem_pthread.dylib 0xab8 thread_start + 8
Thread 0 libsystem_pthread.dylib 0xaa4 start_wqthread + 442
Thread 0 libsystem_pthread.dylib 0xaa4 start_wqthread + 442
Thread 0 libsystem_pthread.dylib 0xaa4 start_wqthread + 442
Thread 0 libsystem_kernel.dylib 0xa90 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0xa58 _pthread_wqthread + 368 2 libsystem_pthread.dylib 0xaac start_wqthread + 8
Thread 0 libsystem_kernel.dylib 0xa90 __workq_kernreturn + 8 1 libsystem_pthread.dylib 0xa58 _pthread_wqthread + 368 2 libsystem_pthread.dylib 0xaac start_wqthread + 8
Thread 0 libsystem_kernel.dylib 0xce4 mach_msg2_trap + 8 1 libsystem_kernel.dylib 0x439c mach_msg2_internal + 76 2 libsystem_kernel.dylib 0x42b8 mach_msg_overwrite + 428 3 libsystem_kernel.dylib 0x4100 mach_msg + 24 4 CoreFoundation 0x11900 __CFRunLoopServiceMachPort + 160 5 CoreFoundation 0x101f0 __CFRunLoopRun + 1208 6 CoreFoundation 0x11c3c CFRunLoopRunSpecific + 572 7 Foundation 0xf79c -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 8 testAppIot 0x4b456c -[AWSIoTStreamThread main] + 98 (AWSIoTStreamThread.m:98) 9 Foundation 0x75804 NSThread__start + 732 10 libsystem_pthread.dylib 0x3344 _pthread_start + 136 11 libsystem_pthread.dylib 0xab8 thread_start + 8