Basic Module Structure
An iOS native module consists of:- A class implementing the
RCTBridgeModuleprotocol - Methods exported with
RCT_EXPORT_METHODmacro - Module registration with
RCT_EXPORT_MODULEmacro
Creating Your First Module
import { NativeModules } from 'react-native';
const { CalendarModule } = NativeModules;
// Call the native method
try {
const eventId = await CalendarModule.createEvent(
'Team Meeting',
'Conference Room A'
);
console.log('Created event:', eventId);
} catch (error) {
console.error('Error creating event:', error);
}
Exporting Methods
Basic Method Export
Use theRCT_EXPORT_METHOD macro to expose methods to JavaScript:
Method Parameters
Supported parameter types:| JavaScript Type | Objective-C Type | Swift Type |
|---|---|---|
boolean | BOOL | Bool |
number | NSInteger, CGFloat, double | Int, Double, Float |
string | NSString | String |
array | NSArray | [Any] |
object | NSDictionary | [String: Any] |
function | RCTResponseSenderBlock | Closure |
Custom Method Names
UseRCT_REMAP_METHOD to specify a different JavaScript name:
Using Callbacks
Single Callback
Error and Success Callbacks
Using Promises
Promises are the preferred way to handle async operations:Exporting Constants
Export constants that are available synchronously in JavaScript:Module Initialization
Controlling Initialization
Accessing React Bridge
Threading
Running on Main Queue
By default, methods run on a background queue. To run on the main queue:Custom Method Queue
Swift Modules
Complete Swift Example
- Swift Module
- Objective-C Bridge
Example: Alert Manager Module
Here’s a real-world example based on React Native’s source code (packages/react-native/React/CoreModules/RCTAlertManager.mm:43-48):Lifecycle Methods
Module Cleanup
Batch Completion
Accessing iOS APIs
Getting Current View Controller
Working with UIKit
Best Practices
- Always handle errors and reject promises appropriately
- Use meaningful error codes and messages
- Run UI operations on the main queue
- Clean up resources in
invalidate - Use promises for async operations
- Document your module’s API
- Mark Swift classes with
@objcfor React Native compatibility - Use
requiresMainQueueSetupto control initialization threading - Validate input parameters before processing