Expo构建React Native iOS应用AppDelegate.m报错求助
Expo React Native iOS 构建错误:AppDelegate.m 编译失败及空白页问题
问题概述
使用Expo构建React Native iOS应用时,AppDelegate.m抛出编译错误,尝试多种修改无效。注释报错代码后构建成功,但手机端仅显示空白页面。
错误信息
❌ (ios/IckonicMobile/AppDelegate.m:15:9) > 15 | #import <AppDelegate.h> | ^ 'AppDelegate.h' file not found with <angled> include; use "quotes" instead ❌ (ios/IckonicMobile/AppDelegate.m:54:29) > 54 | RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:launchOptions]; | ^ property 'reactDelegate' not found on object of type 'AppDelegate *' ❌ (ios/IckonicMobile/AppDelegate.m:59:8) > 59 | self.window.rootViewController = rootViewController; | ^ property 'window' not found on object of type 'AppDelegate *'
问题代码(AppDelegate.m)
#import "AppDelegate.h" // @generated begin react-native-google-cast-import - expo prebuild (DO NOT MODIFY) sync-da0acf16745f87cea5bffba9c0cc3a4f5e4387ea #if __has_include(<GoogleCast/GoogleCast.h>) #import <GoogleCast/GoogleCast.h> #endif // @generated end react-native-google-cast-import #if defined(EX_DEV_MENU_ENABLED) @import EXDevMenu; #endif #if defined(EX_DEV_LAUNCHER_ENABLED) #include <EXDevLauncher/EXDevLauncherController.h> #endif #import <React/RCTBridge.h> #import <React/RCTBundleURLProvider.h> #import <React/RCTRootView.h> #import <React/RCTLinkingManager.h> #import <React/RCTConvert.h> #if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) #import <FlipperKit/FlipperClient.h> #import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h> #import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h> #import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h> #import <SKIOSNetworkAdapter/SKIOSNetworkAdapter.h> #import <FlipperKitReactPlugin/FlipperKitReactPlugin.h> static void InitializeFlipper(UIApplication *application) { FlipperClient *client = [FlipperClient sharedClient]; SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; [client addPlugin:[FlipperKitReactPlugin new]]; [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; [client start]; } #endif @implementation AppDelegate - (RCTBridge *)initializeReactNativeApp:(NSDictionary *)launchOptions { // @generated begin react-native-google-cast-didFinishLaunchingWithOptions - expo prebuild (DO NOT MODIFY) sync-2ad935d6407dfa591d7171af9da1b03d7c763404 #if __has_include(<GoogleCast/GoogleCast.h>) NSString *receiverAppID = kGCKDefaultMediaReceiverApplicationID; GCKDiscoveryCriteria *criteria = [[GCKDiscoveryCriteria alloc] initWithApplicationID:receiverAppID]; GCKCastOptions* options = [[GCKCastOptions alloc] initWithDiscoveryCriteria:criteria]; options.startDiscoveryAfterFirstTapOnCastButton = true; [GCKCastContext setSharedInstanceWithOptions:options]; #endif // @generated end react-native-google-cast-didFinishLaunchingWithOptions RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:launchOptions]; RCTRootView *rootView = [self.reactDelegate createRootViewWithBridge:bridge moduleName:@"main" initialProperties:nil]; rootView.backgroundColor = [UIColor blackColor]; UIViewController *rootViewController = [self.reactDelegate createRootViewController]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return bridge; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { #if defined(FB_SONARKIT_ENABLED) && __has_include(<FlipperKit/FlipperClient.h>) InitializeFlipper(application); #endif self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.backgroundColor = [UIColor blackColor]; #if defined(EX_DEV_LAUNCHER_ENABLED) EXDevLauncherController *controller = [EXDevLauncherController sharedInstance]; [controller startWithWindow:self.window delegate:(id<EXDevLauncherControllerDelegate>)self launchOptions:launchOptions]; #else [self initializeReactNativeApp:launchOptions]; #endif [super application:application didFinishLaunchingWithOptions:launchOptions]; return YES; } - (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge { // If you'd like to export some custom RCTBridgeModules, add them here! return @[]; } - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { #ifdef DEBUG #if defined(EX_DEV_LAUNCHER_ENABLED) return [[EXDevLauncherController sharedInstance] sourceUrl]; #else return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; #endif #else return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; #endif } // Linking API - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options { #if defined(EX_DEV_LAUNCHER_ENABLED) if ([EXDevLauncherController.sharedInstance onDeepLink:url options:options]) { return true; } #endif return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options]; } // Universal Links - (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray<id<UIUserActivityRestoring>> * _Nullable))restorationHandler { BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler]; return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result; } @end #if defined(EX_DEV_LAUNCHER_ENABLED) @implementation AppDelegate (EXDevLauncherControllerDelegate) - (void)devLauncherController:(EXDevLauncherController *)developmentClientController didStartWithSuccess:(BOOL)success { developmentClientController.appBridge = [self initializeReactNativeApp:[EXDevLauncherController.sharedInstance getLaunchOptions]]; } @end #endif
解决方案
1. 修复头文件引用错误
将AppDelegate.m中的#import <AppDelegate.h>改为#import "AppDelegate.h"。尖括号用于系统/框架头文件,引号用于项目本地头文件。
2. 修正AppDelegate.h的继承与属性声明
打开ios/IckonicMobile/AppDelegate.h,替换为以下内容:
#import <Foundation/Foundation.h> #import <React/RCTAppDelegate.h> #import <UIKit/UIKit.h> #if defined(EX_DEV_LAUNCHER_ENABLED) #import <EXDevLauncher/EXDevLauncherController.h> #endif @interface AppDelegate : RCTAppDelegate #if defined(EX_DEV_LAUNCHER_ENABLED) @property (nonatomic, weak) id<EXDevLauncherControllerDelegate> devLauncherDelegate; #endif @end
- 继承
RCTAppDelegate:Expo预构建的AppDelegate必须继承此类,它已内置reactDelegate和window属性的声明。 - 保留
EXDevLauncher相关协议:如果启用了开发启动器,需维持协议引用。
3. 清理缓存并重新构建
执行以下步骤彻底清除缓存并重建:
- 重新生成iOS原生文件:
npx expo prebuild --clean - 进入iOS目录:
cd ios - 清除Xcode构建缓存:
xcodebuild clean - 重新安装Pods:
pod install - 重新构建应用:
npx expo run:ios或通过Xcode启动
4. 解决空白页问题
若注释代码后出现空白页,说明JS bundle未正确加载:
- 检查
sourceURLForBridge方法的路径是否正确,Debug模式下确保本地Metro服务器已启动。 - 验证
moduleName:@"main"与app.json中的name字段完全一致。 - 通过Xcode控制台查看JS报错信息,定位具体加载失败原因。
内容的提问来源于stack exchange,提问作者Lukas Slivka
相关产品推荐
相关产品推荐

