Skip to content

_OBJC_CLASS_$_RCTRootContentView undefined symbol linker error on React Native 0.85 (New Architecture) #43

Description

@fabilo-au

Environment

  • react-native-ios-utilities: 5.2.0
  • react-native-ios-context-menu: 3.2.1
  • React Native: 0.85.3
  • New Architecture (bridgeless): enabled
  • Build: EAS / Xcode archive

Description

Building for iOS fails at link time with:

  Undefined symbols for architecture arm64:
    "_OBJC_CLASS_$_RCTRootContentView", referenced from:
         in libreact-native-ios-utilities.a[48](RCTView+Helpers.o)
  ld: symbol(s) not found for architecture arm64
  clang: error: linker command failed with exit code 1

The error originates in ios/Sources/Extensions+Helpers/RCTView+Helpers.swift, which directly references RCTRootContentView
as a Swift type:

  var closestParentReactContentView: RCTRootContentView? {
      let targetType = RCTRootContentView.self;
      ...
  }

This creates a hard linker dependency on _OBJC_CLASS_$_RCTRootContentView. The symbol is present in the React Native
headers (React/Base/RCTRootContentView.h) but is not exported from the prebuilt React.xcframework included with RN 0.85
under New Architecture / bridgeless mode.

Workaround

Replace the direct type reference with a runtime lookup via NSClassFromString to avoid the hard symbol dependency:

  var closestParentReactContentView: UIView? {
      guard let targetClass = NSClassFromString("RCTRootContentView") else { return nil }

      var current: UIView? = self.superview
      while let view = current {
          if view.isKind(of: targetClass) { return view }
          current = view.superview
      }

      guard let rootView = self.rootViewForCurrentWindow else { return nil }

      var queue = rootView.subviews
      while !queue.isEmpty {
          let view = queue.removeFirst()
          if view.isKind(of: targetClass) { return view }
          queue.append(contentsOf: view.subviews)
      }

      return nil
  }

The call-site in closestParentReactTouchHandler also needs updating since the return type changes from RCTRootContentView?
to UIView?:

// before
return closestParentReactContentView?.reactTouchHandlers?.first

// after
return closestParentReactContentView?.gestureRecognizers?.compactMap { $0 as? RCTTouchHandler }.first

On New Architecture builds where RCTRootContentView doesn't exist, NSClassFromString returns nil and touch-handler
cancellation on context menu presentation becomes a graceful no-op.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions