[React Native] Write Native Module in Swift

ReactNative-0.63.3XCode-12

Introduction

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.

Creating a React Native project

If you don't have a project yet, create one.

npx react-native init myApp

Create a Swift file with XCode

Open the project in ʻios / myApp.xcodeproj` in XCode.

Create a NativeModules folder. (Any)

Create a .swift file in the Native Modules folder.

スクリーンショット 2020-10-09 16.15.25.png

ʻCreate Objective-C Bridging Header`

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"

Implement the method

To get started, let's implement the simplest native module. Change the value of the counter.

Counter.swift


import [email protected](Counter)
class Counter: NSObject {

  private var count = 0

  @objc
  func increment() {
    count += 1
    print("count is \(count)")
  }
}

Make methods available from React Native

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.

スクリーンショット 2020-10-09 16.51.20.png

Add the following to the created file.

Counter.m


@interface RCT_EXTERN_MODULE(Counter, NSObject)
  RCT_EXTERN_METHOD(increment)
@end

About RCT_EXTERN_METHOD

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
)

Call from React Native

You can import NativeModules and call it with class name.method.

import { NativeModules } from 'react-native'

NativeModules.Counter.increment(1));

Handle Event Emitter

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();

[Warning] Module requires main queue setup

The following warning may appear.

スクリーンショット 2020-10-09 22.41.02.png

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

Summary

I summarized how to write a native module in Swift.

Recommended Posts

[React Native] Write Native Module in Swift
React Native Alert Example – Show Alert in React Native App
How to write React Native bridge ~ Android version ~
React Native vs. Ionic – A head-to-head Comparison in 2020
Compare objects in Swift
Division becomes 0 in Swift
Multidimensional array in Swift
Write class inheritance in Ruby
Write Processing in IntelliJ IDEA
Write flyway callbacks in Java
Photo library in Swift UI
Write Java8-like code in Java8
Implement Swift UITextField in code
Write rich text in Clojure