在iOS Share Extension中使用React Native 0.60.4遇sharedApplication不可用问题求助
Hey there, I’ve been through similar headaches trying to get React Native working in app extensions—let’s break down how to fix the sharedApplication is unavailable error and get your Share Extension up and running with RN 0.60.4.
1. Patch React Native Core to Avoid sharedApplication Calls
The root issue is that React Native’s core libraries (like RCTUtils.m) use [UIApplication sharedApplication], which is forbidden in app extensions. Instead of modifying RN source directly (which is hard to maintain), use a Podfile post-install hook to patch these files automatically:
Add this to your Podfile:
post_install do |installer| installer.pods_project.targets.each do |target| if target.name == "React-Core" # Patch RCTUtils.m to handle extension environment rn_utils_path = "#{installer.sandbox.root}/React/Core/RCTUtils.m" system("sed -i '' 's/\\[UIApplication sharedApplication\\]/TARGET_IS_EXTENSION ? nil : \\[UIApplication sharedApplication\\]/g' #{rn_utils_path}") end end end
This replaces every instance of [UIApplication sharedApplication] with a check for whether we’re in an extension, using Apple’s built-in TARGET_IS_EXTENSION macro.
2. Fix Third-Party Libraries (Like FBSDK)
For libraries like FBSDK that also call sharedApplication, apply a similar approach:
- If the library is distributed via CocoaPods, add another patch in the post-install hook. For example, for FBSDKCoreKit:
if target.name == "FBSDKCoreKit" fb_path = "#{installer.sandbox.root}/FBSDKCoreKit/FBSDKCoreKit/FBSDKInternalUtility.m" system("sed -i '' 's/\\[UIApplication sharedApplication\\]/TARGET_IS_EXTENSION ? nil : \\[UIApplication sharedApplication\\]/g' #{fb_path}") end - If patching isn’t feasible, consider forking the library to add extension-safe checks, or look for alternative libraries that support app extensions.
3. Set Up the Share Extension’s React Native Environment
Add RN Dependencies to the Extension Target
In Xcode, go to your Share Extension target’s Build Phases > Link Binary With Libraries and add necessary React Native frameworks (e.g., React, RCTBridge, RCTRootView). You can also add these via Podfile:
target 'YourShareExtension' do pod 'React', :path => '../node_modules/react-native/' pod 'React-Core', :path => '../node_modules/react-native/React' # Add other RN dependencies your extension needs end
Initialize the RN Bridge in Your Extension’s View Controller
Modify your ShareViewController to initialize the React Native bridge and root view:
#import <React/RCTBridge.h> #import <React/RCTRootView.h> #import <React/RCTBundleURLProvider.h> @interface ShareViewController () <RCTBridgeDelegate> @property (nonatomic, strong) RCTBridge *bridge; @end @implementation ShareViewController - (void)viewDidLoad { [super viewDidLoad]; // Initialize RN bridge self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil]; // Create RN root view for extension UI RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:self.bridge moduleName:@"ShareExtensionRNApp" initialProperties:nil]; rootView.frame = self.view.bounds; [self.view addSubview:rootView]; } // Provide JS bundle URL for RN - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #ifdef DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.share" fallbackResource:nil]; #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } @end
Create a Separate RN Entry File
Make a new index.share.js in your RN project root—this will be your extension’s UI entry point:
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const ShareExtensionRNApp = () => { return ( <View style={styles.container}> <Text style={styles.text}>Hello from RN Share Extension!</Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#fff', }, text: { fontSize: 18, fontWeight: 'bold', }, }); export default ShareExtensionRNApp;
4. Configure Extension Settings
- In your Share Extension’s
Info.plist, ensure correct extension configuration:<key>NSExtension</key> <dict> <key>NSExtensionPrincipalClass</key> <string>$(PRODUCT_MODULE_NAME).ShareViewController</string> <key>NSExtensionAttributes</key> <dict> <key>NSExtensionActivationRule</key> <string>SUBQUERY (extensionItems, $extensionItem, SUBQUERY ($extensionItem.attachments, $attachment, ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.url" OR ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.text").@count >= 1).@count >= 1</string> </dict> <key>NSExtensionPointIdentifier</key> <string>com.apple.share-services</string> </dict> - Ensure your extension’s Bundle Identifier is a suffix of your main app’s (e.g.,
com.yourapp.main→com.yourapp.main.ShareExtension).
5. Compile and Debug
- Watch for duplicate symbol errors—if they occur, set any RN libraries linked to both main app and extension to Do Not Embed in one target (usually the extension).
- To debug, select your Share Extension target in Xcode, run it, and choose a sharing-compatible app (like Safari) to trigger the extension. Use the RN debugger as usual by shaking the device (or simulator debug menu).
内容的提问来源于stack exchange,提问作者Jovan

