You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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. 清理缓存并重新构建

执行以下步骤彻底清除缓存并重建:

  1. 重新生成iOS原生文件:npx expo prebuild --clean
  2. 进入iOS目录:cd ios
  3. 清除Xcode构建缓存:xcodebuild clean
  4. 重新安装Pods:pod install
  5. 重新构建应用:npx expo run:ios 或通过Xcode启动

4. 解决空白页问题

若注释代码后出现空白页,说明JS bundle未正确加载:

  • 检查sourceURLForBridge方法的路径是否正确,Debug模式下确保本地Metro服务器已启动。
  • 验证moduleName:@"main"与app.json中的name字段完全一致。
  • 通过Xcode控制台查看JS报错信息,定位具体加载失败原因。

内容的提问来源于stack exchange,提问作者Lukas Slivka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 18:46:02