React native custom IOS native UI component

With React Native, all view components written in javascript can be rendered in both IOS and Android with one codebase. However, when a native IOS UI component is not available in React Native lib yet, the following are the basic steps needed to create a IOS native ui component, bridge it react native and use javascript to render the custom view component written in native IOS.

1. In XCode, create a new file: File -> New -> File… -> Cocoa Touch Class, name it NativeCustomView and add the following. This file is the main content for the custom view.

import UIKit

class NativeCustomView: UIView {

  @objc var message: String? = "Hello Native Custom View" {
    didSet {
      self.setupView()
    }
  }
  
  @objc var bgColor: String? {
    didSet {
      self.setupView()
    }
  }

  @objc var onClick: RCTBubblingEventBlock?

  override init(frame: CGRect) {
    super.init(frame: frame)
    setupView()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setupView()
  }
  
  private func hexStringToUIColor (hex:String) -> UIColor {
      var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

      if (cString.hasPrefix("#")) {
          cString.remove(at: cString.startIndex)
      }

      if ((cString.count) != 6) {
          return UIColor.gray
      }

      var rgbValue:UInt64 = 0
      Scanner(string: cString).scanHexInt64(&rgbValue)

      return UIColor(
          red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
          green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
          blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
          alpha: CGFloat(1.0)
      )
  }
  
  private func setupView() {
    // set background color received from react native
    self.backgroundColor = (self.bgColor != nil) ? hexStringToUIColor(hex: self.bgColor!) : .red

    // make the view clickable
    self.isUserInteractionEnabled = true
    
    // add a text view and set the message received from react native
    let textView = UITextView()
    textView.center = self.center
    textView.textAlignment = NSTextAlignment.center
    textView.textColor = UIColor.blue
    textView.backgroundColor = UIColor.lightGray
    textView.text = self.message
    textView.isEditable = false
    textView.sizeToFit()
    self.addSubview(textView)

    // center the text view
    textView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      textView.widthAnchor.constraint(equalToConstant: 260),
      textView.heightAnchor.constraint(equalToConstant: 30),
      textView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
      textView.centerYAnchor.constraint(equalTo: self.centerYAnchor)
    ])
  }

  // when the view is clicked, send click event with some data to react native
  override func touchesEnded(_ touches: Set, with event: UIEvent?) {
    guard let onClick = self.onClick else { return }

    let params: [String : Any] = ["receivedBgColor":self.bgColor,"receivedMessage": self.message, "response":"hey, you've touched screen."]
    onClick(params)
  }

}

2. In XCode, create another file with the same name NativeCustomView but choose Object c file: File -> New -> File… -> Objective-C File, and add the following. This file defines the properties for the custom view and expose them to React Native.

#import 

// NativeCustomViewManager maps to NativeCustomView in react native requireNativeComponent('NativeCustomView');
// message maps to the message prop on react native's view property
// bgColor maps to the bgColor prop on react native's view property
// onClick maps to the onClick prop on react native's view property
@interface RCT_EXTERN_MODULE(NativeCustomViewManager, RCTViewManager)
RCT_EXPORT_VIEW_PROPERTY(message, NSString)
RCT_EXPORT_VIEW_PROPERTY(bgColor, NSString)
RCT_EXPORT_VIEW_PROPERTY(onClick, RCTBubblingEventBlock)
@end

3. On step 2, when creating the Object-C File, XCode will ask if you want to create a bridge file, select yes to create it. It will create a file YourProjectName-Bridgin-Header.h, open this file and add the following.

//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
#import 
#import 
#import 
#import 
#import 
#import 

4. Create another swift file and name it NativeCustomViewManager, this registers NativeCustomView with React Native.

@objc (NativeCustomViewManager)
class NativeCustomViewManager: RCTViewManager {

  override static func requiresMainQueueSetup() -> Bool {
    return true
  }

  override func view() -> UIView! {
    return NativeCustomView()
  }

}

5. Back to the React Native using any IDE such as VSCode for javascript development, create a file NativeCustomView.tsx with the following.

import { requireNativeComponent } from 'react-native';

//Error "Tried to register two views with the same name AdMobView"
//will be thrown during hot reload when any change is made to the
//file that is calling this requireNativeComponent('AdMobView') call.
//Leaving this on its own file will resolve this issue.
const NativeCustomView = requireNativeComponent('NativeCustomView');
export default NativeCustomView;

6. Create another file to render the custom view MyNativeCustomView.tsx

mport React from 'react';
import { StyleProp, ViewStyle } from 'react-native';
import NativeCustomView from './NativeCustomView';

type IProps = {
  message: String,
  bgColor: String,
  onClick: Function,
  style: StyleProp | undefined,
}

const MyNativeCustomView: React.FC = (props) => {

  const {message, bgColor, onClick, style} = props;
  const _onClick = (event) => {
    if (!onClick) {
      return;
    }

    onClick(event.nativeEvent);
  }

  return 
};
export default MyNativeCustomView;

7. Lastly, you can render MyNativeCustomView anywhere in your react native codebase like this


   {
      console.log("Click event: " + JSON.stringify(event))
    }}
    style={{ width: '100%', height: 100 }}
  />

8. Reinstall the app

react-native run-ios

9. The custom view should display the message ‘Hello, React Native IOS custom view’ with green background, click on the custom view, a log should be printed with something like this: Click event: {“receivedBgColor”:”#4CAF50″,”response”:”hey, you’ve touched screen.”,”receivedMessage”:”Hello, React Native IOS custom view”,”target”:425}

Reference:
https://reactnative.dev/docs/native-components-ios

Search within Codexpedia

Custom Search

Search the entire web

Custom Search