Let's dive deep into creating powerful native modules that bridge JavaScript and iOS seamlessly. โจ
๐ ๏ธ Step-by-Step: Create a Native Module in Swift
Letโs build a simple module called MyNativeModule
that:
- Sends data from JS to iOS ๐ค
- Sends events from iOS to JS ๐ฉ
1๏ธโฃ Create MyNativeModule.swift (Swift) ๐ป
๐ File: MyNativeModule.swift
import Foundation
import React
@objc(MyNativeModule)
class MyNativeModule: RCTEventEmitter {
// MARK: - JS โ iOS
@objc
func receivedData(_ params: NSDictionary, callback: RCTResponseSenderBlock) {
print("๐ฆ Received from JS:", params)
// callback(["โ
iOS received your data!"])
}
// MARK: - iOS โ JS
@objc
func triggerMessageToRN() {
let eventData: [String: Any] = ["message": "๐ Hello from iOS! ๐"]
sendEvent(withName: "onMessageFromNative", body: eventData)
}
// MARK: - Required Overrides
override func supportedEvents() -> [String] {
return ["onMessageFromNative"]
}
override static func requiresMainQueueSetup() -> Bool {
return true
}
}
๐ This class extends RCTEventEmitter to support two-way communication.
2๏ธโฃ Create Objective-C Bridge (MyNativeModule.m
) ๐
Even though youโre using Swift, React Native still requires an Objective-C header to expose the module to JS.
๐ File: MyNativeModule.m
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
@interface RCT_EXTERN_MODULE(MyNativeModule, NSObject)
RCT_EXTERN_METHOD(receivedData:(NSDictionary *)params callback:(RCTResponseSenderBlock)callback)
RCT_EXTERN_METHOD(triggerMessageToRN:(NSDictionary *)params callback:(RCTResponseSenderBlock)callback)
@end
๐ This bridges Swift methods to the RN JS runtime.
๐ง Using the Native Module in JS (React Native Side)
Letโs test our newly created native module in a sample React Native app:
๐ File: App.js
import React, {useEffect} from 'react';
import {
StyleSheet,
View,
Text,
Button,
NativeModules,
NativeEventEmitter,
} from 'react-native';
const {MyNativeModule} = NativeModules;
const eventEmitter = new NativeEventEmitter(MyNativeModule);
const App = () => {
useEffect(() => {
const subscription = eventEmitter.addListener(
'onMessageFromNative',
data => {
console.log('๐จ Message from iOS:', data.message);
}
);
return () => subscription.remove();
}, []);
const sendDataToiOS = () => {
MyNativeModule.receivedData(
{ userName: '[email protected]', age: '29' },
response => console.log('โ
Callback from iOS:', response)
);
};
return (
<View style={styles.container}>
<Text style={styles.title}>๐ React Native + Swift Bridge</Text>
<Button title="๐ค Send Data to iOS" onPress={sendDataToiOS} />
<Button
title="๐จ Receive Event from iOS"
onPress={() => MyNativeModule.triggerMessageToRN()}
/>
</View>
);
};
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
title: {
fontSize: 20,
marginBottom: 20,
fontWeight: 'bold',
},
});
โ Results
๐งช Try it out:
- Tap Send Data to iOS โ Check Xcode logs for received data.
- Tap Trigger iOS to JS โ Watch for JS console logs like ๐จ Message from iOS: Hello from iOS! ๐.
โ๏ธ Troubleshooting Tips
โ
Clean your build folder (Cmd + Shift + K)
โ
Make sure RCT_EXTERN_MODULE is present
โ
Check that Swift is correctly initialized in your project
โ
Use use_frameworks! in your Podfile for Swift support
๐ Final Thoughts
It easier and faster to bridge native code with JavaScript. With TurboModules, native communication is now more optimized and type-safe.
๐ก Whether youโre building a native camera module, voice recognition, or secure authentication โ the same pattern applies.
๐ฌ Drop a Comment
Was this guide helpful? Stuck somewhere?
Drop a comment below๐
๐ Donโt forget to like and share to help others in the RN community!
Top comments (0)