Minimal reproduction: AnylineNativeView crashes inside a react-navigation screen on iOS (anyline-ocr-react-native-module 56.5.0)
  • TypeScript 56.4%
  • Ruby 22.5%
  • Swift 20.2%
  • C 0.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Dominic Cohrs 41ee5fb152 Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS)
anyline-ocr-react-native-module 56.5.0 (same code in 56.4.0), React Native
0.81.5, Expo SDK 54, New Architecture — the same versions as the plugin's own
example/RNExampleApp, plus react-navigation.

No Anyline license key and no scan are involved: the app terminates while React
mounts the native view. AnylineNativeViewManager.m attaches a helper
UIViewController to the application's root view controller, while the container
view handed to React is mounted under the current screen's view controller
(RNSScreen). UIKit's hierarchy check then raises
UIViewControllerHierarchyInconsistency.

App.tsx offers three placements of the same component (mounted into the visible
screen, mounted during the push transition, mounted at the app root) so the
difference is the mount point and the moment of mounting, nothing else.
patches/ contains a one-function workaround.
2026-09-10 10:56:44 +02:00
assets Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
ios Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
patches Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
.gitignore Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
app.json Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
App.tsx Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
index.ts Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
package-lock.json Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
package.json Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
README.md Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00
tsconfig.json Minimal reproduction: AnylineNativeView crashes in a react-navigation screen (iOS) 2026-09-10 10:56:44 +02:00

AnylineNativeView crash reproduction (iOS)

Minimal app that demonstrates: mounting AnylineNativeView into a react-navigation screen that is already on screen terminates the app on iOS.

No Anyline license key and no scan are involved. The app dies while React mounts the native view, so requestSdkInitialization and requestScanStart are never called.

*** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency'

child view controller:<UIViewController: 0x…>
should have parent view controller:<RNSScreen: 0x…>
but actual parent is:<UIViewController: 0x…>

Versions

anyline-ocr-react-native-module 56.5.0 (identical code in 56.4.0)
React Native 0.81.5, React 19.1.0, New Architecture enabled
Expo SDK 54 — same versions as example/RNExampleApp
Navigation @react-navigation/native 7.2.2, native-stack 7.14.12, react-native-screens 4.16.0
Verified with Xcode 26.6, iOS 18.6 Simulator

Run it

npm install
npx expo prebuild -p ios --clean     # downloads Anyline.xcframework (~198 MB), runs pod install
npx expo run:ios                     # or open ios/AnylineNativeViewRepro.xcworkspace in Xcode

The three cases

The app mounts the same component in three places, so only the mount point and the moment of mounting differ.

What it does Result
A Open the screen, then press “Mount now” — the view is added to a screen that is already in the window App terminates, exception above
B Mount the view while the screen is being pushed No crash
C Mount the same component at the app root, outside the navigator No crash — a grey box appears

Two conditions have to meet for the crash:

  1. The container view is mounted into a hierarchy that is already in a window. During a push transition the screen is not in the window yet, so UIKit never runs its hierarchy check — case B. In a real app condition 1 is met on every re-mount: going back and re-entering the scan screen, or toggling the view for a fallback UI. That is how we ran into it on device.
  2. The nearest ancestor view controller is not the app's root view controller. Case C mounts under the root view controller, where the plugin's assumption happens to hold.

To see the exception text rather than a silent termination, run from Xcode with an Objective-C exception breakpoint (breakpoint set -E objc, then po $rdi).

Cause

ios/NativeView/AnylineNativeViewManager.m in the plugin:

- (UIView *)view {
  UIView *containerView = [[UIView alloc] init];

  NSString *containerId = [NSString stringWithFormat:@"%d", 0];
  [[NativeViewRegistry shared] registerView:containerView withId:containerId];

  UIViewController *vc = [[UIViewController alloc] init];
  vc.view.frame = containerView.bounds;
  vc.view.backgroundColor = [UIColor lightGrayColor];

  UIViewController *rootVC = UIApplication.sharedApplication.delegate.window.rootViewController;
  [rootVC addChildViewController:vc];   // <-- parent hardcoded to the app's root VC
  [containerView addSubview:vc.view];
  [vc didMoveToParentViewController:rootVC];

  return containerView;
}

React mounts containerView wherever the app places the component. With react-navigation's native stack the owning view controller is an RNSScreen, not the application's root view controller, so UIKit's check fails while the subtree is moved into the window:

-[UIView(Hierarchy) _associatedViewControllerForwardsAppearanceCallbacks:performHierarchyCheck:isRoot:]
-[UIView(Hierarchy) _willMoveToWindow:withAncestorView:]
_makeSubTreePerformSelector
-[UIView(Internal) _addSubview:positioned:relativeTo:]
-[RCTViewComponentView mountChildComponentView:index:]

example/RNExampleApp cannot surface this because it uses no navigation library, so all views sit directly under the root view controller — case C above.

Workaround

Removing the helper view controller fixes it; the SDK only needs the registered container view (-[AnylineInfinityPlugin getContainerView]NativeViewRegistry.getLastOrNull):

- (UIView *)view {
  UIView *containerView = [[UIView alloc] init];
  containerView.backgroundColor = [UIColor blackColor];

  NSString *containerId = [NSString stringWithFormat:@"%d", 0];
  [[NativeViewRegistry shared] registerView:containerView withId:containerId];

  return containerView;
}

With that change case A no longer crashes, and in our own app the embedded scan view works normally inside a navigation screen: preview, cutout, flash button and results. Android already behaves this way — NativeFragmentContainerView is a plain FrameLayout that only registers itself, and it also cleans up in onDropViewInstance, which iOS does not do at all.

Try it here:

patch -p0 < patches/AnylineNativeViewManager.m.patch   # apply
npx expo run:ios
patch -R -p0 < patches/AnylineNativeViewManager.m.patch  # revert

Files

Path What it is
App.tsx the whole reproduction — three mount points, ~120 lines
patches/AnylineNativeViewManager.m.patch the workaround, as a plain patch against node_modules