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

React Native iOS模板转Swift遇黑屏,求转换方案及无桥接调用方法

Hey there! Let's tackle your React Native + Swift issues step by step— I’ve helped plenty of devs make this switch with RN 0.52, so let’s get your app out of that black screen and clarify the Swift bridging question.

Fixing the Black Screen When Switching to Swift AppDelegate in RN 0.52 + Swift Bridging FAQs

First: Correct Steps to Convert RN Template to Swift AppDelegate (RN 0.52 Compatible)

The black screen usually comes from missing configuration steps or mismatched setup. Let’s walk through the exact process that works for this RN version:

1. Clean Up Old Objective-C Files

First, get rid of the default OC files:

  • Delete AppDelegate.m and ViewController.m from your project (make sure to select "Move to Trash" to remove them entirely).
  • You can keep main.m for now, but we’ll handle that later.

2. Create Your Swift AppDelegate

  • Make a new Swift file named AppDelegate.swift. When Xcode asks if you want to create a bridging header, select "Don’t Create" (we don’t need it just for the AppDelegate, and I’ll explain why later).
  • Paste this code into the file, replacing YourProjectName with the actual name of your RN project (the one you used when running react-native init):
    import UIKit
    import React
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
        var window: UIWindow?
        var bridge: RCTBridge!
    
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            // Set up the JS bundle location
            let jsCodeLocation: URL
            #if DEBUG
            jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index", fallbackResource: nil)
            #else
            jsCodeLocation = Bundle.main.url(forResource: "main", withExtension: "jsbundle")!
            #endif
    
            // Initialize RN bridge and root view
            bridge = RCTBridge(delegate: self, launchOptions: launchOptions)
            let rootView = RCTRootView(bridge: bridge, moduleName: "YourProjectName", initialProperties: nil)
    
            // Set up the window with RN's root view
            window = UIWindow(frame: UIScreen.main.bounds)
            let rootViewController = UIViewController()
            rootViewController.view = rootView
            window?.rootViewController = rootViewController
            window?.makeKeyAndVisible()
    
            return true
        }
    
        // Required RCTBridgeDelegate method
        func sourceURL(for bridge: RCTBridge!) -> URL! {
            #if DEBUG
            return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index", fallbackResource: nil)
            #else
            return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
            #endif
        }
    
        // Handle deep links (optional but recommended)
        func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
            return RCTLinkingManager.application(application, open: url, options: options)
        }
    }
    

3. Tweak Project Configurations

  • Go to your project’s Build Settings, search for Main Interface, and clear the field (since we’re using @UIApplicationMain to launch the app, we don’t need a storyboard entry point).
  • Check your Info.plist: Make sure NSAppTransportSecurity > NSAllowsArbitraryLoads is set to YES— this is required for RN 0.52 to load the local JS bundle in debug mode.
  • If you deleted ViewController.m, double-check Info.plist and remove the Main storyboard file base name entry (or set it to empty) so Xcode doesn’t try to load a non-existent storyboard.

4. Optional: Remove main.m

Since we’re using @UIApplicationMain on our Swift AppDelegate, Xcode will automatically generate the app’s entry point. You can safely delete main.m now— if you see an error, just double-check that the @UIApplicationMain annotation is at the top of your AppDelegate class.

5. Rebuild and Run

  • First, run npm install to make sure all dependencies are up to date.
  • In Xcode, clean the build folder with Cmd+Shift+K, then build with Cmd+B, and finally run with Cmd+R. Make sure Metro is running (you can start it with npx react-native start if it’s not).

Second: Can You Call Swift Code Without a Bridging Header in RN 0.52?

Short answer: Not fully, but you can avoid writing a custom bridging header for basic cases (like just using a Swift AppDelegate).

Here’s the breakdown:

  • RN 0.52’s core bridge is still built on Objective-C. For RN to call your Swift code, Swift needs to expose itself to the Objective-C runtime.
  • If you’re only replacing the AppDelegate with Swift (no need to expose custom Swift modules to RN), you don’t need a bridging header at all— the code we wrote above works because we’re conforming to RN’s Objective-C protocols (like RCTBridgeDelegate) using Swift’s @objc compatibility.
  • If you want to create custom Swift modules that RN can call, you’ll need to use the auto-generated bridging files:
    1. When you create your first Swift module, Xcode will offer to make a YourProjectName-Bridging-Header.h— keep this file (you don’t need to add anything to it for basic cases).
    2. Mark your Swift class and methods with @objc and dynamic so the Objective-C runtime can see them:
      @objc class SwiftUtils: NSObject {
          @objc dynamic func getGreeting() -> String {
              return "Hey from Swift!"
          }
      }
      
    3. You don’t need to import anything into the bridging header— instead, Xcode auto-generates a YourProjectName-Swift.h file that Objective-C can use. For RN, you can just call the module directly from JS:
      import { NativeModules } from 'react-native';
      const { SwiftUtils } = NativeModules;
      console.log(SwiftUtils.getGreeting());
      

Why Did Your Previous Attempt Result in a Black Screen?

Most likely one of these issues:

  • You didn’t replace YourProjectName in the moduleName field of RCTRootView— RN couldn’t find your root component.
  • The Main Interface setting wasn’t cleared, so Xcode tried to load a default storyboard instead of RN’s root view.
  • Metro wasn’t running, so the JS bundle failed to load.
  • You had leftover references to deleted Objective-C files causing compilation conflicts.

Go through the steps above, and you should get past the black screen in no time.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:29:45