LibraryWriting Objective-C/Swift code for modules

Writing Objective-C/Swift code for modules

Learn about Writing Objective-C/Swift code for modules as part of React Native Cross-Platform Mobile Development

Native Modules & Bridging in React Native: Objective-C/Swift

React Native allows you to leverage native platform capabilities by writing custom native modules. This is crucial when you need to access device-specific APIs, integrate existing native code, or achieve performance optimizations not possible with JavaScript alone. This module focuses on writing these native modules using Objective-C and Swift for iOS.

Understanding the Bridge

The React Native bridge is the communication layer between your JavaScript code and the native Objective-C/Swift code. It serializes and deserializes data, enabling asynchronous communication. Understanding this bridge is key to designing efficient native modules.

The bridge facilitates communication between JavaScript and native code.

The React Native bridge acts as a conduit, translating calls and data between the JavaScript thread and the native threads (UI and Native Modules). This allows your JavaScript code to invoke native methods and receive results asynchronously.

The bridge operates by sending messages between the JavaScript VM and the native side. When a JavaScript function calls a native method, a message is sent to the native thread. The native module executes the requested operation and, if necessary, sends a response back to JavaScript. This process involves serialization and deserialization of arguments and return values, which can introduce overhead if not managed carefully. Asynchronous operations are fundamental to the bridge's design to prevent blocking the UI thread.

Creating a Native Module in Objective-C

To create a native module in Objective-C, you'll typically define a class that inherits from

code
NSObject
and conforms to the
code
RCTBridgeModule
protocol. You'll also need to expose methods to JavaScript using the
code
RCT_EXPORT_MODULE()
and
code
RCT_EXPORT_METHOD()
macros.

What are the primary macros used to expose an Objective-C class as a React Native module and its methods?

RCT_EXPORT_MODULE() and RCT_EXPORT_METHOD()

Here's a basic structure for an Objective-C native module:

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

@interface MyNativeModule : NSObject <RCTBridgeModule>
@end

// MyNativeModule.m
#import "MyNativeModule.h"

@implementation MyNativeModule

RCT_EXPORT_MODULE(); // Exports the module

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
  NSLog(@"Adding event: %@ at %@", name, location);
  // Native logic to add an event
}

RCT_EXPORT_METHOD(multiply:(float)a withB:(float)b
                  callback:(RCTResponseSenderBlock)callback) {
  callback(@[@(a*b)]);
}

@end

This code defines a module MyNativeModule with two exported methods: addEvent which takes string arguments, and multiply which takes two floats and a callback to send a result back to JavaScript. The NSLog statement demonstrates how to log messages from the native side.

📚

Text-based content

Library pages focus on text content

Creating a Native Module in Swift

Swift modules follow a similar pattern. You'll create a Swift class and use the

code
@objc
attribute to make it visible to the Objective-C runtime, along with the
code
RCT_EXPORT_MODULE
and
code
RCT_EXPORT_METHOD
macros. You'll need to ensure your Swift file is correctly configured in your Xcode project.

Here's a basic structure for a Swift native module:

swift
// MySwiftModule.swift
import Foundation
import React
@objc(MySwiftModule)
class MySwiftModule: NSObject {
@objc
func constantsToExport() -> [String: Any] {
return ["someConstant": "Hello from Swift!"]
}
@objc
func greet(_ name: String, callback: @escaping RCTResponseSenderBlock) {
let greeting = "Hello, \(name)!"
callback([greeting])
}
@objc
static func requiresMainQueueSetup() -> Bool {
return true // If your module needs to run on the main thread
}
}

This Swift module

code
MySwiftModule
exports a constant and a
code
greet
method. The
code
requiresMainQueueSetup
method is important if your module needs to interact with the UI or other main thread-bound APIs.

Handling Data Types and Callbacks

The bridge supports various data types, including strings, numbers, booleans, arrays, and dictionaries. For asynchronous operations or returning multiple values, you'll use

code
RCTResponseSenderBlock
(Objective-C) or
code
RCTResponseSenderBlock
(Swift) as a callback parameter. You can also use
code
RCTPromiseResolveBlock
and
code
RCTPromiseRejectBlock
for Promise-based operations.

JavaScript TypeObjective-C/Swift TypeNotes
StringNSString / StringDirect mapping
NumberNSNumber / Double, Float, IntUse appropriate numeric types
BooleanBOOL / BoolDirect mapping
ArrayNSArray / ArrayNested structures are supported
ObjectNSDictionary / DictionaryNested structures are supported
Function (Callback)RCTResponseSenderBlockUsed for asynchronous responses
PromiseRCTPromiseResolveBlock, RCTPromiseRejectBlockModern approach for async operations

Best Practices

Minimize bridge calls and data transfer. Batch operations where possible to reduce overhead and improve performance.

When writing native modules, consider the following:

  • Thread Safety: Ensure your module's methods are thread-safe, especially if they access shared resources.
  • Error Handling: Implement robust error handling using Promises or callbacks to inform JavaScript of issues.
  • Main Thread Execution: Use
    code
    requiresMainQueueSetup
    in Swift or
    code
    mainQueueSetup
    in Objective-C if your module needs to interact with the UI or other main thread APIs.
  • Performance: Be mindful of the data being passed across the bridge. Large data transfers can impact performance.

Learning Resources

Native Modules | React Native Documentation(documentation)

The official React Native documentation provides a comprehensive overview of native modules, including how to create them in Objective-C and Swift.

Bridging to Native Code | React Native Documentation(documentation)

This guide explains the concept of bridging and how to create native UI components, which shares similar principles with native modules.

React Native Native Module Tutorial (Swift)(video)

A video tutorial demonstrating how to create a native module using Swift in React Native.

React Native Native Module Tutorial (Objective-C)(video)

A video tutorial showcasing the process of building a native module with Objective-C for React Native.

Understanding the React Native Bridge(blog)

A detailed blog post explaining the inner workings of the React Native bridge and its importance.

Swift Native Modules in React Native(blog)

A practical guide on creating and using Swift native modules within a React Native application.

Objective-C Native Modules in React Native(blog)

A practical guide on creating and using Objective-C native modules within a React Native application.

React Native: Native Modules(documentation)

Specific documentation for creating native modules on the iOS platform, covering both Objective-C and Swift.

React Native Architecture: The Bridge(blog)

An article that delves into the architecture of React Native, with a focus on the role and function of the bridge.

Swift Programming Language Guide(documentation)

The official Swift documentation, useful for understanding Swift syntax and features when writing native modules.