Skip to content

fix(ios): patch maplibre ViewManager to skip old-arch registration on new arch#1559

Merged
CraigBuckmaster merged 1 commit into
masterfrom
fix/maplibre-mlrncamera-double-registration
Apr 21, 2026
Merged

fix(ios): patch maplibre ViewManager to skip old-arch registration on new arch#1559
CraigBuckmaster merged 1 commit into
masterfrom
fix/maplibre-mlrncamera-double-registration

Conversation

@CraigBuckmaster
Copy link
Copy Markdown
Owner

Summary

Fixes Invariant Violation: Tried to register two views with the same name MLRNCamera crash on MapScreen mount under RN New Architecture. This crash was previously masked by the first-launch crash fixed in #1557 / #1558; once the app reaches the main tabs, tapping Map triggers this separate invariant violation, propagates past MapErrorBoundary to RCTFatal → SIGABRT.

Root cause

maplibre-react-native@11.0.0-beta.31 (the latest beta and — verified — iOS-identical to the just-released v11.0.0 stable) still ships old-architecture ViewManager subclasses (MLRNCameraManager, MLRNMapViewManager) alongside its new-arch Fabric ComponentViews. The shared ViewManager base class unconditionally inherits from RCTViewManager, so RN's legacy-interop scanner auto-registers those subclasses under view names "MLRNCamera" / "MLRNMapView" — the same names Codegen has already claimed via RCTThirdPartyComponentsProvider.mm for the Fabric components. Two registrations, same name, boom.

I verified upstream has not yet fixed this: zero RCT_NEW_ARCH_ENABLED guards in the entire ios/ tree, and git diff v11.0.0-beta.31..v11.0.0 shows zero iOS changes.

Fix

Single-file patch-package diff against ViewManager.h: conditional inheritance based on RCT_NEW_ARCH_ENABLED.

  • Under new arch → @interface ViewManager : NSObject — removes the class from RN's RCTViewManager scanner, eliminating the legacy registration path.
  • Under old arch → unchanged (: RCTViewManager), preserving backwards compatibility if new arch is ever toggled off.

Why this is safe

I grepped the entire library's iOS source to confirm:

Check Result
Any class that alloc/init/news MLRNCameraManager or MLRNMapViewManager Zero — instance construction never happens
Classes inheriting directly from RCTViewManager (not via ViewManager) One — only the ViewManager base itself
Classes inheriting from ViewManager Two — only MLRNCameraManager and MLRNMapViewManager
RCT_EXPORT_VIEW_PROPERTY / RCT_EXPORT_MODULE macros Zero across the entire ObjC source
Call sites referencing MLRN*Manager classes on new-arch paths All class-method invocations[MLRNCameraManager handleImperativeStop:...], [MLRNMapViewManager getCenter:...], etc.
Callers of fireEvent:withCallback: (the ViewManager instance method) Zero outside the base class file itself — dead on new arch

On new arch, these "Manager" classes are pure class-method namespaces for helpers the TurboModule code calls. Their RCTViewManager lineage is pure cruft from incomplete migration. Swapping the base class to NSObject preserves every symbol the Codegen/TurboModule paths reference while cleanly removing the legacy registration.

Files changed

  • app/patches/@maplibre+maplibre-react-native+11.0.0-beta.31.patch (new file, 41 insertions)

No changes to package.json, Podfile, app.config.js, or any JS/TS. patch-package is already in postinstall, so this takes effect automatically on next npm install.

Verification plan (rentamac)

git checkout fix/maplibre-mlrncamera-double-registration
cd app && rm -rf node_modules && npm install
# postinstall should print:  @maplibre/maplibre-react-native@11.0.0-beta.31 ✔

# Sanity-check the patched content is on disk
grep -A1 RCT_NEW_ARCH_ENABLED node_modules/@maplibre/maplibre-react-native/ios/components/ViewManager.h
# Expected:
#   #ifdef RCT_NEW_ARCH_ENABLED
#   @interface ViewManager : NSObject

cd ios && pod install
# Xcode: Clean Build Folder → Build → Run on iPhone 17 Pro sim (iOS 26.4), Release config

# In the app:
#  1. App launches, onboarding runs, main tabs render (iOS 26 fix still holds)
#  2. Tap Map tab — previous crash point
#  3. MapScreen renders without Invariant Violation / RCTFatal / SIGABRT
#  4. Navigate away and back a few times — confirm no re-registration crash on re-mount

If the map shows blank tiles but renders without crashing, that's network/tiles and a separate issue — this PR's scope is crash-only.

Rollback

rm app/patches/@maplibre+maplibre-react-native+11.0.0-beta.31.patch
cd app && rm -rf node_modules && npm install && cd ios && pod install

Patch is additive; deletion fully reverts.

Ship sequence

Because the fix is native, an eas update OTA will not deliver it. After merge: eas build --platform ios --profile production to produce a fresh TestFlight build containing both the iOS 26 fix (already on master from #1557/#1558) and this Map fix.

Follow-up (not blocking)

  • File upstream issue on maplibre/maplibre-react-native describing the double-registration so they ship arch-guarded managers in v11.0.1 / v11.1. When that lands, drop this patch.
  • Kanban card: "Drop @maplibre patch when upstream ships arch-guarded managers."

… new arch

Prevents 'Invariant Violation: Tried to register two views with the same
name MLRNCamera' crash on MapScreen mount under RN New Architecture.

Root cause: maplibre-react-native v11.0.0-beta.31 still ships old-arch
ViewManager subclasses (MLRNCameraManager, MLRNMapViewManager) alongside
the new-arch Fabric ComponentViews. Because the ViewManager base class
unconditionally inherits from RCTViewManager, RN's legacy-interop scanner
auto-registers those subclasses under view names ('MLRNCamera',
'MLRNMapView') that Codegen has already claimed for the Fabric
component views. Both paths register — invariant violation at runtime.

Fix: one-line conditional inheritance in the ViewManager base class —
subclass NSObject when RCT_NEW_ARCH_ENABLED is defined, keep RCTViewManager
otherwise. Removes the managers from RN's registration scanner while
preserving every class symbol the TurboModules reference.

Verified:
- Managers are never instantiated anywhere in the library (pure class-method
  namespaces on new arch)
- Only the 'ViewManager' base class inherits from RCTViewManager directly
- Only MLRNCameraManager and MLRNMapViewManager inherit from ViewManager
- Zero RCT_EXPORT_VIEW_PROPERTY macros anywhere in the ObjC source
- v11.0.0 stable has identical iOS source to beta.31 (no upstream fix yet)

Remove this patch when maplibre-react-native ships arch-guarded managers
upstream. File upstream issue tracked as follow-up kanban card.
@github-actions
Copy link
Copy Markdown

Test Results

✅ All tests passed

Passed Failed Total
Tests ✅ 3433 ❌ 0 3433
Suites ✅ 466 ❌ 0 466

Coverage

Statements Branches Functions Lines

⏱️ Duration: 79.3s

@CraigBuckmaster CraigBuckmaster merged commit dda8ce3 into master Apr 21, 2026
6 checks passed
@CraigBuckmaster CraigBuckmaster deleted the fix/maplibre-mlrncamera-double-registration branch April 21, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant