To access the native iOS API, React Natve provides an API called Native Module
.
This time, I will summarize how to implement a native module in Swift
.
If you don't have a project yet, create one.
npx react-native init myApp
Open the project in ʻios / myApp.xcodeproj` in XCode.
Create a NativeModules
folder. (Any)
Create a .swift
file in the Native Modules
folder.
When you create a .swift
file, XCode will ask you if you want to create a ʻObjective-C Bridging Header`.
This file, as the name implies, bridges the Swift and ʻObjective-C` files. Do not change the file name.
Add to ʻObjective-C Bridging Header` as follows.
myApp-Bridging-Header.h
// myApp-Bridging-Header.h
#import"React/RCTBridgeModule.h"
To get started, let's implement the simplest native module. Change the value of the counter.
Counter.swift
import Foundation@objc(Counter)
class Counter: NSObject {
private var count = 0
@objc
func increment() {
count += 1
print("count is \(count)")
}
}
Create an Objective-C` file so that the implemented method can be handled from React Native.
Create it in the same directory with the same name as the Swift file you created earlier.
Add the following to the created file.
Counter.m
@interface RCT_EXTERN_MODULE(Counter, NSObject)
RCT_EXTERN_METHOD(increment)
@end
The methods described in RCT_EXTERN_METHOD
can be used in React Native.
If the method has no arguments, write as follows.
RCT_EXTERN_METHOD(methodName)
If there is an argument, write as follows.
RCT_EXTERN_METHOD(
methodName: (paramType1)internalParamName1
)
For example, if the ʻincrement method requires an argument, the
swift` file looks like this:
@objc
func increment(_ num: Int) {
...
}
The corresponding RCT_EXTERN_METHOD
looks like this:
RCT_EXTERN_METHOD(
increment: (Int)num
)
You can import NativeModules
and call it with class name.method
.
import { NativeModules } from 'react-native'
NativeModules.Counter.increment(1));
Use RCTEventEmitter
when you want to Sunscribe an event that occurs on the iOS native side.
Write the following in the ʻObjective-C` file.
#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"
@interface RCT_EXTERN_MODULE(Counter, RCTEventEmitter)
In addition, add it to the bridge file.
CounterApp-Bridging-Header.h
#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"
Implement the following in your Swift file:
--sendEvent
: Describe the event name and its contents
--supportedEvents
: Describe the event name when pasting the listener on the React Native side
@objc(Counter)
class Counter: RCTEventEmitter {
@objc
func increment() {
count += 1
print("count is \(count)")
sendEvent(withName: "onIncrement", body: ["count": count])
}
override func supportedEvents() -> [String]! {
return ["onIncrement"]
}
}
On the React Native side, the event listener listens.
import {
NativeModules,
NativeEventEmitter
} from 'react-native'
const CounterEvents = new NativeEventEmitter(NativeModules.Counter);
CounterEvents.addListener(
"onIncrement",
(res) => console.log(res)
);
NativeModules.Counter.increment();
The following warning may appear.
This is a warning to set whether the module should be processed in the main thread or in the background. You can turn off the warning by writing as follows.
@objc
static func requiresMainQueueSetup() -> Bool {
return true
}
--Returns true
: Processed by main thread
--Returns false
: Processed in the background
I summarized how to write a native module in Swift.
Recommended Posts