Featured

Integrating a React Native Screen into a Native iOS App

 

Integrating a React Native Screen into a Native iOS App

Integrating React Native into an existing native iOS project can be a powerful way to leverage the flexibility of JavaScript-based UI development while keeping the performance benefits of native code. In this guide, we'll go through the entire process step-by-step, addressing common issues and solutions along the way.


1. Setting Up the Project Structure

Before starting, let’s assume we have the following project structure:

/ios-native-app/    <-- Your native iOS project
│   ├── Podfile
│   ├── AppDelegate.swift
│   ├── ViewController.swift
│   ├── ...
│
/react-native-module/    <-- Your React Native project
    ├── node_modules/
    ├── package.json
    ├── index.js
    ├── ios/ (if it exists)
    ├── android/
    ├── src/

This setup allows us to keep React Native separate from our native iOS project.


2. Installing React Native Dependencies

To use React Native inside our iOS project, we need to install dependencies. In the React Native directory, run:

npm install  # or yarn install

If your native iOS project does not yet include CocoaPods, initialize it with:

cd ios-native-app
pod init

3. Adding React Native to the iOS Project

We need to add React Native dependencies to the iOS app. Open the Podfile located in the ios-native-app directory and add the following:

pod 'React-Core'
pod 'React-RCTBridge'
pod 'React-RCTDevSupport'
pod 'React-RCTImage'
pod 'React-RCTText'
pod 'React-RCTNetwork'
pod 'React-RCTAnimation'
pod 'React-RCTActionSheet'
pod 'React-RCTLinking'
pod 'React-RCTSettings'
pod 'React-RCTBlob'
pod 'React-RCTFileSystem'
pod 'React-RCTWebSocket'
pod 'ReactCommon'
pod 'Yoga'

Then, install the dependencies:

pod install

4. Configuring the JavaScript Bundle

By default, React Native runs a Metro bundler in development mode. However, in release mode, we need a static JS bundle inside the native app.

4.1. Creating the Bundle

To generate the JavaScript bundle manually, run:

npx react-native bundle --platform ios --entry-file index.js --bundle-output ios/main.jsbundle --assets-dest ios

This will create main.jsbundle, which can be used in release builds.

4.2. Loading the Bundle in iOS Code

Modify the view controller where you want to load the React Native screen:

import UIKit
import React

class NotificationsViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        #if DEBUG
        // Load from Metro Bundler in debug mode
        let jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index", fallbackExtension: nil)
        #else
        // Load from bundled JS file in release mode
        let jsCodeLocation = Bundle.main.url(forResource: "main", withExtension: "jsbundle")
        #endif

        guard let url = jsCodeLocation else { return }
        let rootView = RCTRootView(bundleURL: url, moduleName: "NotificationsScreen", initialProperties: nil, launchOptions: nil)
        self.view = rootView
    }
}

This ensures that in development mode, the app connects to Metro, while in production, it loads the bundled JavaScript file.


5. Fixing Common Issues

5.1. Assets.car Duplication Error

If you get an error about Multiple commands produce 'Assets.car', go to:

  • Xcode → Build Phases → Copy Bundle Resources

  • Ensure Assets.car appears only once. If it exists multiple times, remove the duplicate entry.

5.2. Firebase/CoreInternal Not Found

If you face a CocoaPods issue like:

[!] CocoaPods could not find compatible versions for pod "Firebase/CoreInternal"

Run:

pod repo update
pod install --repo-update

5.3. node_modules/ Not Ignored by Git

If your .gitignore file is not excluding node_modules, check with:

git check-ignore -v node_modules/

If it’s not ignored, manually add:

node_modules/
/node_modules

Commit the changes:

git rm -r --cached node_modules/
git commit -m "Fixed node_modules ignore issue"

6. Running the App

Finally, to test the integration:

6.1. Debug Mode (Using Metro Server)

In the React Native directory, start Metro:

npx react-native start

Then run the iOS app in Xcode.

6.2. Release Mode (Without Metro Server)

Ensure the bundle is generated:

npx react-native bundle --platform ios --entry-file index.js --bundle-output ios/main.jsbundle --assets-dest ios

Then build the app in Xcode for release.


Conclusion

This guide covered:

  • Setting up React Native within a native iOS app

  • Installing necessary dependencies via CocoaPods

  • Loading React Native screens dynamically

  • Handling Metro bundler in debug and release modes

  • Fixing common integration errors

By following these steps, you can successfully integrate and display a React Native screen within a native iOS project, ensuring smooth cross-platform development. 🚀

Comments

Popular Posts