DEV Community

Cover image for Bridging Native iOS Code with React Native Using Swift: A Step-by-Step Guide
Amit Kumar
Amit Kumar

Posted on • Updated on

Bridging Native iOS Code with React Native Using Swift: A Step-by-Step Guide

Introduction

When building mobile apps with React Native, there may be times when you need to access platform-specific features that are unavailable via JavaScript. Fortunately, React Native provides a way to bridge native functionality to the JavaScript layer, allowing you to leverage platform-specific APIs. In this blog, we'll walk through how to create a bridge between React Native and native iOS code using Swift, using a simple calculator example.


Why Bridging in React Native for iOS?

While React Native provides several built-in APIs, there are cases when you need to access native iOS functionality for performance gains or to use specific features unavailable in JavaScript. Bridging allows you to:

  • Access iOS-specific APIs: This could include APIs for handling gestures, audio, and other hardware-accelerated features.
  • Leverage native frameworks: Swift frameworks like Core Location, Core Data, or AVFoundation can be used directly in your app.
  • Integrate third-party native SDKs: Sometimes, React Native libraries don’t exist for the SDK you need, and bridging lets you directly integrate the native version.

Setting Up Your React Native Project for Native Code

Before we begin coding, we need to ensure that your React Native project is configured to handle native Swift code.

  • 1. Install Xcode: Ensure you have Xcode installed on your machine.
  • 2. Open the iOS folder: Navigate to the iOS folder of your React Native project and open it in Xcode using this command:
cd ios && open MyReactNativeApp.xcworkspace

Enter fullscreen mode Exit fullscreen mode
  • 3. Create a Swift File: In Xcode, right-click on the project navigator and select New File > Swift File. Name the file CalculatorModule.swift.
  • 4. Create a Bridging Header: When prompted to create a bridging header, accept it. The bridging header allows Objective-C (used by React Native) to interact with Swift code.

Image description

Image description

Image description

Image description

Image description

Image description

Image description

Image description

Now, your project is ready for native code integration.


Writing the Native Module in Swift

Let’s start by creating a CalculatorModule that exposes an add method to React Native.

In your CalculatorModule.swift, add the following code:

import Foundation
import React

@objc(CalculatorModule)
class CalculatorModule: NSObject {

  @objc
  func add(_ a: NSNumber, b: NSNumber, callback: @escaping RCTResponseSenderBlock) {
    let sum = a.doubleValue + b.doubleValue
    callback([NSNull(), sum])  // Sending the result back to JavaScript
  }

  static func requiresMainQueueSetup() -> Bool {
    return false
  }
}

Enter fullscreen mode Exit fullscreen mode

CalculatorModule Swift file screenshot

Explanation:

  • @objc(CalculatorModule): This exposes the Swift class to Objective-C, making it available in JavaScript.
  • add(_ a: NSNumber, b: NSNumber, callback: @escaping RCTResponseSenderBlock): The add method accepts two numbers (a and b), computes their sum, and returns the result through a callback. The NSNumber type ensures compatibility with Objective-C.
  • requiresMainQueueSetup(): React Native uses this to determine if the module should be initialized on the main thread. Returning false is fine unless your code involves UI updates.

Exposing the Native Module to React Native

We also need to tell React Native about the existence of this native module. This is done by creating an Objective-C file.

Create a new Objective-C file named CalculatorModule.m and add the following:

#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>

@interface RCT_EXTERN_MODULE(CalculatorModule, NSObject)
 RCT_EXTERN_METHOD(add:(nonnull NSNumber *)a b:(nonnull NSNumber *)b callback:(RCTResponseSenderBlock)callback)
@end

Enter fullscreen mode Exit fullscreen mode

Image description

Explanation:

  • RCT_EXTERN_MODULE(CalculatorModule, NSObject): This macro exposes the Swift class CalculatorModule to React Native.
  • RCT_EXTERN_METHOD(add:b:callback:): This exposes the add method to JavaScript, specifying its parameters and callback.

Using the Native Module in React Native

Now that the native module is ready, we can call the add function from JavaScript. Here’s an example of how to do that:

import { NativeModules } from 'react-native';
const { CalculatorModule } = NativeModules;

CalculatorModule.add(5, 10, (error, sum) => {
  if (error) {
    console.error(error);
  } else {
    console.log('Sum is:', sum); // Output: Sum is: 15
  }
});

Enter fullscreen mode Exit fullscreen mode

In this JavaScript code:

  • We import the CalculatorModule from NativeModules.
  • We call the add method, passing two numbers (5 and 10) and a callback to handle the result.

To send data to iOS side

To send data from React Native to the native side in the CalculatorModule, your setup works similarly to the previous example. Here's a recap with the updated module name:

The receivedData method in CalculatorModule:

@objc
  func receivedData(_ params: NSDictionary) {    
    Log.d("data-->>", params)

    val userName = params["userName"] as? String ?? ""
    val userAge = params["userAge"] as? Int ?? 23
  }
Enter fullscreen mode Exit fullscreen mode

React Native Side

From the React Native side, you send the data using:

NativeModules.HelloWorldModule.receivedData({
    userName: "amit@gmail.com",
    age: "29",
});
Enter fullscreen mode Exit fullscreen mode

Conclusion

By bridging native iOS code with React Native, you can unlock powerful native features and optimize your app’s performance. In this tutorial, we created a simple calculator module in Swift, exposed it to React Native, and used it in the JavaScript layer. This same method can be extended to integrate any iOS functionality into your React Native app.

Native bridging opens the door to fully customizing your app’s capabilities, allowing you to integrate platform-specific code while still maintaining a common JavaScript codebase. Start exploring native modules, and enhance your React Native apps today!

After reading the post consider the following:

  • Subscribe to receive newsletters with the latest blog posts
  • Download the source code for this post from my github

Top comments (0)