react / react/react-native

Text with custom fonts is invisible in iOS App Extensions (Fabric / New Architecture)

Open
#56,309 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Needs: Triage :mag: Platform: iOS Type: New Architecture
Dominant language
C++
Stars
127k
Forks
25.3k
Avg merge
1d 23h
Merged PRs (30d)
4

Description

When using React Native 0.84+ with the new architecture in an iOS App Extension (Share Extension, Action Extension, etc.), all <Text> components that use a custom fontFamily are invisible. Text using the system font renders fine, but with the wrong size.

Setting allowFontScaling={false} on individual <Text> components works around the issue.

Root Cause

RCTFontSizeMultiplier() in React/Fabric/Surface/RCTFabricSurface.mm calls:

return mapping[RCTSharedApplication().preferredContentSizeCategory].floatValue;

In App Extensions, RCTSharedApplication() returns nil (because UIApplication.sharedApplication is unavailable in extensions). This causes:

  1. nil.preferredContentSizeCategorynil
  2. mapping[nil]nil
  3. nil.floatValue0.0

This 0.0 is stored as layoutContext.fontSizeMultiplier, which propagates to all text measurement:

// In RCTFontWithFontProperties (prebuilt binary):
CGFloat effectiveFontSize = fontProperties.sizeMultiplier * fontProperties.size;
// effectiveFontSize = 0.0 * 14.0 = 0.0

System fonts survive because [UIFont systemFontOfSize:0] returns a 12pt default font. But custom fonts fail because [UIFont fontWithName:@"CustomFont" size:0] returns nil, falling through to a Helvetica fallback with incorrect metrics — resulting in zero-sized text layout.

Proposed Fix

Replace RCTSharedApplication().preferredContentSizeCategory with UITraitCollection.currentTraitCollection.preferredContentSizeCategory, which works in both apps and extensions:

// Before (broken in extensions):
return mapping[RCTSharedApplication().preferredContentSizeCategory].floatValue;

// After (works everywhere):
NSString *category;
if (!RCTRunningInAppExtension()) {
    category = RCTSharedApplication().preferredContentSizeCategory;
} else {
    category = UITraitCollection.currentTraitCollection.preferredContentSizeCategory;
}
return mapping[category ?: UIContentSizeCategoryLarge].floatValue;

This also correctly handles Dynamic Type accessibility settings in extensions, which the current code silently ignores.

Workarounds

Per-component (JS)
<Text style={{ fontFamily: 'Inter-Regular' }} allowFontScaling={false}>
  This text will be visible
</Text>
Native swizzle (ObjC++)

Swizzle RCTFabricSurface._updateLayoutContext to correct fontSizeMultiplier from 0 to 1.0 after the original implementation sets it. See ShareExtensionReactHelper.mm in the main project for a working implementation.

Steps to reproduce
  1. Clone this https://github.com/erkie/react-native-font-scaling-repro
  2. npm install && cd ios && bundle exec pod install && cd ..
  3. npm run ios
  4. Open Safari, navigate to any page, tap Share → select "FontScalingReproShareExtension"
React Native Version

0.84.1

Affected Platforms

Runtime - iOS

Areas

Fabric - The New Renderer

Output of npx @react-native-community/cli info
System:
  OS: macOS 26.3.1
  CPU: (14) arm64 Apple M4 Pro
  Memory: 172.81 MB / 48.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 24.13.0
    path: /Users/thingtesting/.local/state/fnm_multishells/75626_1775109555064/bin/node
  Yarn: Not Found
  npm:
    version: 11.6.2
    path: /Users/thingtesting/.local/state/fnm_multishells/75626_1775109555064/bin/npm
  Watchman:
    version: 2025.05.26.00
    path: /opt/homebrew/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /Users/thingtesting/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 25.0
      - iOS 26.0
      - macOS 26.0
      - tvOS 26.0
      - visionOS 26.0
      - watchOS 26.0
  Android SDK:
    API Levels:
      - "34"
      - "35"
      - "36"
    Build Tools:
      - 34.0.0
      - 35.0.0
      - 36.0.0
    System Images:
      - android-34 | Google APIs ARM 64 v8a
      - android-34 | Google APIs Intel x86_64 Atom
    Android NDK: Not Found
IDEs:
  Android Studio: 2025.2 AI-252.27397.103.2522.14617522
  Xcode:
    version: 26.0/17A324
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.16
    path: /opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home/bin/javac
  Ruby:
    version: 3.4.5
    path: /Users/thingtesting/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 20.1.0
    wanted: 20.1.0
  react:
    installed: 19.2.3
    wanted: 19.2.3
  react-native:
    installed: 0.84.1
    wanted: 0.84.1
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true
Stacktrace or Logs
Please review screenshots
MANDATORY Reproducer

https://github.com/erkie/react-native-font-scaling-repro

Screenshots and Videos

Inside app, works with custom fonts
Image

Inside share extension, invisible texts
Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in React/Fabric/Surface/RCTFabricSurface.mm at RCTFontSizeMultiplier(), then run the linked react-native-font-scaling-repro setup and reproduce the issue in its share extension. Verify the change against custom-font Text components, system fonts, and Dynamic Type behavior in an app extension. Done means custom-font text is visible with correct scaling without requiring allowFontScaling={false}.

Written by the indexing model from the issue text.

Assessment

Tech stack
ios, objective-c, react-native
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.