mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
76 lines
163 KiB
HTML
76 lines
163 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="generator" content="Docusaurus v2.0.0-alpha.66">
|
||
<link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="React Native Blog RSS Feed">
|
||
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="React Native Blog Atom Feed">
|
||
<link rel="preconnect" href="https://www.google-analytics.com">
|
||
<script>window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)},ga.l=+new Date,ga("create","UA-41298772-2","auto"),ga("send","pageview")</script>
|
||
<script async src="https://www.google-analytics.com/analytics.js"></script>
|
||
<link rel="preconnect" href="https://www.google-analytics.com">
|
||
<link rel="preconnect" href="https://www.googletagmanager.com">
|
||
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-41298772-2"></script>
|
||
<script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","UA-41298772-2",{})</script>
|
||
<link rel="search" type="application/opensearchdescription+xml" title="React Native" href="/opensearch.xml">
|
||
<script src="https://cdn.jsdelivr.net/npm/focus-visible@5.2.0/dist/focus-visible.min.js" defer="defer"></script>
|
||
<script src="https://snack.expo.io/embed.js" defer="defer"></script><title data-react-helmet="true">iOS Native Modules · React Native</title><meta data-react-helmet="true" property="twitter:image" content="https://reactnative.dev/img/logo-og.png"><meta data-react-helmet="true" name="twitter:image:alt" content="Image for React Native"><meta data-react-helmet="true" name="docsearch:language" content="en"><meta data-react-helmet="true" name="docsearch:version" content="0.63"><meta data-react-helmet="true" name="docsearch:docusaurus_tag" content="docs-default-0.63"><meta data-react-helmet="true" property="og:image" content="https://reactnative.dev/img/logo-og.png"><meta data-react-helmet="true" name="twitter:card" content="summary"><meta data-react-helmet="true" name="twitter:image" content="https://reactnative.dev/img/logo-og.png"><meta data-react-helmet="true" property="og:title" content="iOS Native Modules · React Native"><meta data-react-helmet="true" name="description" content="Welcome to Native Modules for iOS. Please start by reading the Native Modules Intro for an intro to what native modules are."><meta data-react-helmet="true" property="og:description" content="Welcome to Native Modules for iOS. Please start by reading the Native Modules Intro for an intro to what native modules are."><meta data-react-helmet="true" property="og:url" content="https://reactnative.dev/docs/native-modules-ios"><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.ico"><link data-react-helmet="true" rel="preconnect" href="https://BH4D9OD16A-dsn.algolia.net" crossorigin="anonymous"><link data-react-helmet="true" rel="canonical" href="https://reactnative.dev/docs/native-modules-ios"><link rel="stylesheet" href="/styles.654d26b0.css">
|
||
<link rel="stylesheet" href="/main.c541a094.css">
|
||
<link rel="preload" href="/styles.cc2cf098.js" as="script">
|
||
<link rel="preload" href="/runtime~main.19ca5e97.js" as="script">
|
||
<link rel="preload" href="/main.259a8b48.js" as="script">
|
||
<link rel="preload" href="/1.55a8a1b3.js" as="script">
|
||
<link rel="preload" href="/2.8585ac8b.js" as="script">
|
||
<link rel="preload" href="/1f391b9e.8301d553.js" as="script">
|
||
<link rel="preload" href="/939.3c971b89.js" as="script">
|
||
<link rel="preload" href="/ee5b3385.4adebc95.js" as="script">
|
||
<link rel="preload" href="/17896441.6dff1a67.js" as="script">
|
||
<link rel="preload" href="/54bb2e43.e2b3c64c.js" as="script">
|
||
</head>
|
||
<body>
|
||
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
|
||
<nav class="navbar navbar--fixed-top navbar--dark"><div class="navbar__inner"><div class="navbar__items"><div aria-label="Navigation bar toggle" class="navbar__toggle" role="button" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></div><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/header_logo.svg" alt="React Native"><strong class="navbar__title">React Native</strong></a><div class="navbar__item dropdown dropdown--hoverable dropdown--left"><a class="navbar__item navbar__link" href="/docs/getting-started">0.63</a><ul class="dropdown__menu"><li><a class="dropdown__link" href="/docs/next/native-modules-ios">Next</a></li><li><a aria-current="page" class="dropdown__link dropdown__link--active" href="/docs/native-modules-ios">0.63</a></li><li><a class="dropdown__link" href="/docs/0.62/native-modules-ios">0.62</a></li><li><a class="dropdown__link" href="/docs/0.61/native-modules-ios">0.61</a></li><li><a class="dropdown__link" href="/docs/0.60/native-modules-ios">0.60</a></li><li><a class="dropdown__link" href="/versions">All versions</a></li></ul></div></div><div class="navbar__items navbar__items--right"><a class="navbar__item navbar__link navbar__link--active" href="/docs/getting-started">Docs</a><a class="navbar__item navbar__link" href="/docs/components-and-apis">Components</a><a class="navbar__item navbar__link" href="/docs/accessibilityinfo">API</a><a class="navbar__item navbar__link" href="/help">Community</a><a class="navbar__item navbar__link" href="/blog">Blog</a><a href="https://github.com/facebook/react-native" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link navbar-github-link" aria-label="GitHub repository"></a><div class="react-toggle react-toggle--disabled displayOnlyInLargeViewport_3lWe"><div class="react-toggle-track"><div class="react-toggle-track-check"><span class="toggle_gnXW">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_gnXW">🌞</span></div></div><div class="react-toggle-thumb"></div><input type="checkbox" disabled="" aria-label="Dark mode toggle" class="react-toggle-screenreader-only"></div><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span><span class="DocSearch-Button-Key">⌘</span><span class="DocSearch-Button-Key">K</span></button></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div><div class="navbar-sidebar"><div class="navbar-sidebar__brand"><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/header_logo.svg" alt="React Native"><strong class="navbar__title">React Native</strong></a></div><div class="navbar-sidebar__items"><div class="menu"><ul class="menu__list"><li class="menu__list-item"><a class="menu__link navbar__link--active" href="/docs/getting-started">Docs</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/components-and-apis">Components</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/accessibilityinfo">API</a></li><li class="menu__list-item"><a class="menu__link" href="/help">Community</a></li><li class="menu__list-item"><a class="menu__link" href="/blog">Blog</a></li><li class="menu__list-item"><a role="button" class="menu__link menu__link--sublist">Versions</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" href="/docs/next/native-modules-ios">Next</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link menu__link--active" href="/docs/native-modules-ios">0.63</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/0.62/native-modules-ios">0.62</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/0.61/native-modules-ios">0.61</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/0.60/native-modules-ios">0.60</a></li><li class="menu__list-item"><a class="menu__link" href="/versions">All versions</a></li></ul></li><li class="menu__list-item"><a href="https://github.com/facebook/react-native" target="_blank" rel="noopener noreferrer" class="menu__link navbar-github-link" aria-label="GitHub repository"></a></li></ul></div></div></div></nav><div class="main-wrapper"><div class="docPage_2UBv"><div class="docSidebarContainer_1hqR" role="complementary"><div class="sidebar_MSwm"><div class="menu menu--responsive menu_2hiu"><button aria-label="Open Menu" aria-haspopup="true" class="button button--secondary button--sm menu__button" type="button"><svg aria-label="Menu" class="sidebarMenuIcon_37TU" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 32 32" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><ul class="menu__list"><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">The Basics</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/getting-started">Introduction</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/intro-react-native-components">Core Components and Native Components</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/intro-react">React Fundamentals</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/handling-text-input">Handling Text Input</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/using-a-scrollview">Using a ScrollView</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/using-a-listview">Using List Views</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/troubleshooting">Troubleshooting</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/platform-specific-code">Platform Specific Code</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/more-resources">More Resources</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Environment setup</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/environment-setup">Setting up the development environment</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/integration-with-existing-apps">Integration with Existing Apps</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/building-for-tv">Building For TV Devices</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/out-of-tree-platforms">Out-of-Tree Platforms</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Workflow</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/running-on-device">Running On Device</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/fast-refresh">Fast Refresh</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/debugging">Debugging</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/testing-overview">Testing</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/libraries">Using Libraries</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/typescript">Using TypeScript</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/upgrading">Upgrading to new React Native versions</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Design</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/style">Style</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/height-and-width">Height and Width</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/flexbox">Layout with Flexbox</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/images">Images</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/colors">Color Reference</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Interaction</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/handling-touches">Handling Touches</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/navigation">Navigating Between Screens</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/animations">Animations</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/gesture-responder-system">Gesture Responder System</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Inclusion</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/accessibility">Accessibility</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Performance</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/performance">Performance Overview</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/optimizing-flatlist-configuration">Optimizing Flatlist Configuration</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/ram-bundles-inline-requires">RAM Bundles and Inline Requires</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/profiling">Profiling</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">JavaScript Runtime</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/javascript-environment">JavaScript Environment</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/timers">Timers</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/hermes">Using Hermes</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Connectivity</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/network">Networking</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/security">Security</a></li></ul></li><li class="menu__list-item"><a class="menu__link menu__link--sublist menu__link--active" href="#!">Native Modules</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/native-modules-intro">Native Modules Intro</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/native-modules-android">Android Native Modules</a></li><li class="menu__list-item"><a aria-current="page" class="menu__link menu__link--active active" tabindex="0" href="/docs/native-modules-ios">iOS Native Modules</a></li><li class="menu__list-item"><a class="menu__link" tabindex="0" href="/docs/native-modules-setup">Native Modules NPM Package Setup</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Native Components</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/native-components-android">Android Native UI Components</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/native-components-ios">iOS Native UI Components</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/direct-manipulation">Direct Manipulation</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Guides (Android)</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/headless-js-android">Headless JS</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/signed-apk-android">Publishing to Google Play Store</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/removing-default-permissions">Removing Default Permissions</a></li></ul></li><li class="menu__list-item menu__list-item--collapsed"><a class="menu__link menu__link--sublist" href="#!">Guides (iOS)</a><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/linking-libraries-ios">Linking Libraries</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/running-on-simulator-ios">Running On Simulator</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/communication-ios">Communication between native and React Native</a></li><li class="menu__list-item"><a class="menu__link" tabindex="-1" href="/docs/app-extensions">App Extensions</a></li></ul></li></ul></div></div></div><main class="docMainContainer_1rYT"><div class="container padding-vert--lg docItemWrapper_1Hme"><div class="row"><div class="col docItemCol_2AGf"><div class="docItemContainer_1tAC"><article><header><h1 class="docTitle_cWlf">iOS Native Modules</h1></header><div class="markdown"><p>Welcome to Native Modules for iOS. Please start by reading the <a href="/docs/native-modules-intro">Native Modules Intro</a> for an intro to what native modules are.</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="create-a-calendar-native-module"></a>Create a Calendar Native Module<a aria-hidden="true" tabindex="-1" class="hash-link" href="#create-a-calendar-native-module" title="Direct link to heading">#</a></h2><p>In the following guide you will create a native module, <code>CalendarModule</code>, that will allow you to access Apple's calendar APIs from JavaScript. By the end you will be able to call <code>CalendarModule.createCalendarEvent('Dinner Party', 'My House');</code> from JavaScript, invoking a native method that creates a calendar event.</p><blockquote><p>The React Native team is currently working on a re-architecture of the Native Module system. This new system is called TurboModules, and it will help facilitate more efficient type-safe communication between JavaScript and native, without relying on the React Native bridge. It will also enable new extensions that weren't possible with the legacy Native Module system. You can read more about it <a href="https://github.com/react-native-community/discussions-and-proposals/issues/40" target="_blank" rel="noopener noreferrer">here</a>. Throughout these docs we have added notes around parts of Native Modules that will change in the TurboModules release and how you can best prepare for a smooth upgrade to TurboModules.</p></blockquote><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="setup"></a>Setup<a aria-hidden="true" tabindex="-1" class="hash-link" href="#setup" title="Direct link to heading">#</a></h3><p>To get started, open up the iOS project within your React Native application in Xcode. You can find your iOS project here within a React Native app:</p><figure><img src="/docs/assets/native-modules-ios-open-project.png" width="500" alt="Image of opening up an iOS project within a React Native app inside of xCode."><figcaption>Image of where you can find your iOS project</figcaption></figure><p>We recommend using Xcode to write your native code. Xcode is built for iOS development, and using it will help you to quickly resolve smaller errors like code syntax.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="create-custom-native-module-files"></a>Create Custom Native Module Files<a aria-hidden="true" tabindex="-1" class="hash-link" href="#create-custom-native-module-files" title="Direct link to heading">#</a></h3><p>The first step is to create our main custom native module header and implementation files. Create a new file called <code>RCTCalendarModule.h</code></p><figure><img src="/docs/assets/native-modules-ios-add-class.png" width="500" alt="Image of creating a class called RCTCalendarModule.h."><figcaption>Image of creating a custom native module file within the same folder as AppDelegate</figcaption></figure><p>and add the following to it:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// RCTCalendarModule.h</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> <React/RCTBridgeModule.h></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@interface</span><span class="token plain"> RCTCalendarModule </span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> NSObject </span><span class="token operator" style="color:#fc929e"><</span><span class="token plain">RCTBridgeModule</span><span class="token operator" style="color:#fc929e">></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@end</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><p>You can use any name that fits the native module you are building. Name the class <code>RCTCalendarModule</code> since you are creating a calendar native module. Since ObjC does not have language-level support for namespaces like Java or C++, convention is to prepend the class name with a substring. This could be an abbreviation of your application name or your infra name. RCT, in this example, refers to React.</p><p>As you can see below, the CalendarModule class implements the <code>RCTBridgeModule</code> protocol. A native module is an Objective-C class that implements the <code>RCTBridgeModule</code> protocol.</p><p>Next up, let’s start implementing the native module. Create the corresponding implementation file, <code>RCTCalendarModule.m</code>, in the same folder and include the following content:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// RCTCalendarModule.m</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> "RCTCalendarModule.h"</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@implementation</span><span class="token plain"> RCTCalendarModule</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token comment" style="color:#93a1a1">// To export a module named RCTCalendarModule</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token function" style="color:#79b6f2">RCT_EXPORT_MODULE</span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@end</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="module-name"></a>Module Name<a aria-hidden="true" tabindex="-1" class="hash-link" href="#module-name" title="Direct link to heading">#</a></h3><p>For now, your <code>RCTCalendarModule.m</code> native module only includes a <code>RCT_EXPORT_MODULE</code> macro, which exports and registers the native module class with React Native. The <code>RCT_EXPORT_MODULE</code> macro also takes an optional argument that specifies the name that the module will be accessible as in your JavaScript code.</p><p>This argument is not a string literal. In the example below <code>RCT_EXPORT_MODULE(CalendarModuleFoo)</code> is passed, not <code>RCT_EXPORT_MODULE("CalendarModuleFoo")</code>.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// To export a module named CalendarModuleFoo</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token function" style="color:#79b6f2">RCT_EXPORT_MODULE</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">CalendarModuleFoo</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>The native module can then be accessed in JS like this:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> CalendarModuleFoo </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> ReactNative</span><span class="token punctuation" style="color:#657b83">.</span><span class="token plain">NativeModules</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>If you do not specify a name, the JavaScript module name will match the Objective-C class name, with any "RCT" or "RK" prefixes removed.</p><p>Let's follow the example below and call <code>RCT_EXPORT_MODULE</code> without any arguments. As a result, the module will be exposed to React Native using the name <code>CalendarModule</code>, since that is the Objective-C class name, with RCT removed.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// Without passing in a name this will export the native module name as the Objective-C class name with “RCT” removed</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token function" style="color:#79b6f2">RCT_EXPORT_MODULE</span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>The native module can then be accessed in JS like this:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> CalendarModule </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> ReactNative</span><span class="token punctuation" style="color:#657b83">.</span><span class="token plain">NativeModules</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="export-a-native-method-to-javascript"></a>Export a Native Method to JavaScript<a aria-hidden="true" tabindex="-1" class="hash-link" href="#export-a-native-method-to-javascript" title="Direct link to heading">#</a></h3><p>React Native will not expose any methods in a native module to JavaScript unless explicitly told to. This can be done using the <code>RCT_EXPORT_METHOD</code> macro. Methods written in the <code>RCT_EXPORT_METHOD</code> macro are asynchronous and the return type is therefore always void. In order to pass a result from a <code>RCT_EXPORT_METHOD</code> method to JavaScript you can use callbacks or emit events (covered below). Let’s go ahead and set up a native method for our <code>CalendarModule</code> native module using the <code>RCT_EXPORT_METHOD</code> macro. Call it <code>createCalendarEvent()</code> and for now have it take in name and location arguments as strings. Argument type options will be covered shortly.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">name location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><blockquote><p>Please note that the <code>RCT_EXPORT_METHOD</code> macro will not be necessary with TurboModules unless your method relies on RCT argument conversion (see argument types below). Ultimately, React Native will remove <code>RCT_EXPORT_MACRO,</code> so we discourage people from using <code>RCTConvert</code>. Instead, you can do the argument conversion within the method body.</p></blockquote><p>Before you build out the <code>createCalendarEvent()</code> method’s functionality, add a console log in the method so you can confirm it has been invoked from JavaScript in your React Native application. Use the <code>RCTLog</code> APIs from React. Let’s import that header at the top of your file and then add the log call.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> <React/RCTLog.h></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">name location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">RCTLogInfo</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">@"Pretending to create an event %@ at %@"</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> name</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> location</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="synchronous-methods"></a>Synchronous Methods<a aria-hidden="true" tabindex="-1" class="hash-link" href="#synchronous-methods" title="Direct link to heading">#</a></h3><p>You can use the <code>RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD</code> to create a synchronous native method.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">getName</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">UIDevice currentDevice</span><span class="token punctuation" style="color:#657b83">]</span><span class="token plain"> name</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><p>The return type of this method must be of object type (id) and should be serializable to JSON. This means that the hook can only return nil or JSON values (e.g. NSNumber, NSString, NSArray, NSDictionary).</p><p>At the moment, we do not recommend using synchronous methods, since calling methods synchronously can have strong performance penalties and introduce threading-related bugs to your native modules. Additionally, please note that if you choose to use <code>RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD</code>, your app can no longer use the Google Chrome debugger. This is because synchronous methods require the JS VM to share memory with the app. For the Google Chrome debugger, React Native runs inside the JS VM in Google Chrome, and communicates asynchronously with the mobile devices via WebSockets.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="test-what-you-have-built"></a>Test What You Have Built<a aria-hidden="true" tabindex="-1" class="hash-link" href="#test-what-you-have-built" title="Direct link to heading">#</a></h3><p>At this point you have set up the basic scaffolding for your native module in iOS. Test that out by accessing the native module and invoking it’s exported method in JavaScript.</p><p>Find a place in your application where you would like to add a call to the native module’s <code>createCalendarEvent()</code> method. Below is an example of a component, <code>NewModuleButton</code> you can add in your app. You can invoke the native module inside <code>NewModuleButton</code>'s <code>onPress()</code> function.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">import</span><span class="token plain"> React </span><span class="token keyword" style="color:#c5a5c5">from</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'react'</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> NativeModules</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> Button </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">from</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'react-native'</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">NewModuleButton</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">onPress</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">log</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">'We will invoke the native module here!'</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token tag punctuation" style="color:#657b83"><</span><span class="token tag class-name" style="color:#fac863">Button</span><span class="token tag" style="color:#fc929e"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token tag" style="color:#fc929e"> </span><span class="token tag attr-name" style="color:#c5a5c5">title</span><span class="token tag attr-value punctuation" style="color:#657b83">=</span><span class="token tag attr-value punctuation" style="color:#657b83">"</span><span class="token tag attr-value" style="color:#8dc891">Click to invoke your native module!</span><span class="token tag attr-value punctuation" style="color:#657b83">"</span><span class="token tag" style="color:#fc929e"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token tag" style="color:#fc929e"> </span><span class="token tag attr-name" style="color:#c5a5c5">color</span><span class="token tag attr-value punctuation" style="color:#657b83">=</span><span class="token tag attr-value punctuation" style="color:#657b83">"</span><span class="token tag attr-value" style="color:#8dc891">#841584</span><span class="token tag attr-value punctuation" style="color:#657b83">"</span><span class="token tag" style="color:#fc929e"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token tag" style="color:#fc929e"> </span><span class="token tag attr-name" style="color:#c5a5c5">onPress</span><span class="token tag script language-javascript script-punctuation punctuation" style="color:#657b83">=</span><span class="token tag script language-javascript punctuation" style="color:#657b83">{</span><span class="token tag script language-javascript" style="color:#fc929e">onPress</span><span class="token tag script language-javascript punctuation" style="color:#657b83">}</span><span class="token tag" style="color:#fc929e"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token tag" style="color:#fc929e"> </span><span class="token tag punctuation" style="color:#657b83">/></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">export</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">default</span><span class="token plain"> NewModuleButton</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>In order to access your native module from JavaScript you need to first import <code>NativeNodules</code> from React Native:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> NativeModules </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">from</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'react-native'</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>You can then access the <code>CalendarModule</code> native module off of <code>NativeModules</code>.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> CalendarModule </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> NativeModules</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>Now that you have the CalendarModule native module available, you can invoke your native method <code>createCalendarEvent()</code>. Below it is added to the <code>onPress()</code> method in <code>NewModuleButton</code>:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">onPress</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">'testName'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'testLocation'</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>The final step is to rebuild the React Native app so that you can have the latest native code (with your new native module!) available. In your command line, where the react native application is located, run the following :</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-shell codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">npx react-native run-ios</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="building-as-you-iterate"></a>Building as You Iterate<a aria-hidden="true" tabindex="-1" class="hash-link" href="#building-as-you-iterate" title="Direct link to heading">#</a></h3><p>As you work through these guides and iterate on your native module, you will need to do a native rebuild of your application to access your most recent changes from JavaScript. This is because the code that you are writing sits within the native part of your application. While React Native’s metro bundler can watch for changes in JavaScript and rebuild JS bundle on the fly for you, it will not do so for native code. So if you want to test your latest native changes you need to rebuild by using the <code>npx react-native run-ios</code> command.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="recap"></a>Recap✨<a aria-hidden="true" tabindex="-1" class="hash-link" href="#recap" title="Direct link to heading">#</a></h3><p>You should now be able to invoke your <code>createCalendarEvent()</code> method on your native module in JavaScript. Since you are using <code>RCTLog</code> in the function, you can confirm your native method is being invoked by <a href="https://reactnative.dev/docs/debugging#chrome-developer-tools" target="_blank" rel="noopener noreferrer">enabling debug mode in your app</a> and looking at the JS console in Chrome or the mobile app debugger Flipper. You should see your <code>RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);</code> message each time you invoke the native module method.</p><figure><img src="/docs/assets/native-modules-ios-logs.png" width="1000" alt="Image of logs."><figcaption>Image of iOS logs in Flipper</figcaption></figure><p>At this point you have created an iOS native module and invoked a method on it from JavaScript in your React Native application. You can read on to learn more about things like what argument types your native module method takes and how to setup callbacks and promises within your native module.</p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="beyond-a-calendar-native-module"></a>Beyond a Calendar Native Module<a aria-hidden="true" tabindex="-1" class="hash-link" href="#beyond-a-calendar-native-module" title="Direct link to heading">#</a></h2><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="better-native-module-export"></a>Better Native Module Export<a aria-hidden="true" tabindex="-1" class="hash-link" href="#better-native-module-export" title="Direct link to heading">#</a></h3><p>Importing your native module by pulling it off of <code>NativeModules</code> like above is a bit clunky.</p><p>To save consumers of your native module from needing to do that each time they want to access your native module, you can create a JavaScript wrapper for the module. Create a new JavaScript file named NativeCalendarModule.js with the following content:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">/**</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* This exposes the native CalendarModule module as a JS module. This has a</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* function 'createCalendarEvent' which takes the following parameters:</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="display:inline-block;color:#93a1a1">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* 1. String name: A string representing the name of the event</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* 2. String location: A string representing the location of the event</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">*/</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> NativeModules </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">from</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'react-native'</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> CalendarModule </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> NativeModules</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">export</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">default</span><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>This JavaScript file also becomes a good location for you to add any JavaScript side functionality. For example, if you use a type system like TypeScript you can add type annotations for your native module here. While React Native does not yet support Native to JS type safety, with these type annotations, all your JS code will be type safe. These annotations will also make it easier for you to switch to type-safe native modules down the line. Below is an example of adding type safety to the Calendar Module:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">/**</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* This exposes the native CalendarModule module as a JS module. This has a</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* function 'createCalendarEvent' which takes the following parameters:</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">*</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* 1. String name: A string representing the name of the event</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">* 2. String location: A string representing the location of the event</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">*/</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> NativeModules </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">from</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'react-native'</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> CalendarModule </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> NativeModules</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">interface</span><span class="token plain"> </span><span class="token class-name" style="color:#fac863">CalendarInterface</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">name</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> string</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> string</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">void</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">export</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">default</span><span class="token plain"> CalendarModule </span><span class="token keyword" style="color:#c5a5c5">as</span><span class="token plain"> CalendarInterface</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>In your other JavaScript files you can access the native module and invoke its method like this:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">import</span><span class="token plain"> NativeCalendarModule </span><span class="token keyword" style="color:#c5a5c5">from</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'./NativeCalendarModule'</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">NativeCalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">'foo'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">'bar'</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><blockquote><p>Note this assumes that the place you are importing <code>CalendarModule</code> is in the same hierarchy as <code>CalendarModule.js</code>. Please update the relative import as necessary.</p></blockquote><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="argument-types"></a>Argument Types<a aria-hidden="true" tabindex="-1" class="hash-link" href="#argument-types" title="Direct link to heading">#</a></h3><p>When a native module method is invoked in JavaScript, React Native converts the arguments from JS objects to their Objective-C/Swift object analogues. So for example, if your Objective-C Native Module method accepts a NSNumber, in JS you need to call the method with a number. React Native will handle the conversion for you. Below is a list of the argument types supported for native module methods and the JavaScript equivalents they map to.</p><table><thead><tr><th>Objective-C</th><th>JavaScript</th></tr></thead><tbody><tr><td>NSString</td><td>string, ?string</td></tr><tr><td>BOOL</td><td>boolean</td></tr><tr><td>NSNumber</td><td>?boolean</td></tr><tr><td>double</td><td>number</td></tr><tr><td>NSNumber</td><td>?number</td></tr><tr><td>NSArray</td><td>Array, ?Array</td></tr><tr><td>NSDictionary</td><td>Object, ?Object</td></tr><tr><td>RCTResponseSenderBlock</td><td>Function (success)</td></tr><tr><td>RCTResponseSenderBlock, RCTResponseErrorBlock</td><td>Function (failure)</td></tr><tr><td>RCTPromiseResolveBlock, RCTPromiseRejectBlock</td><td>Promise</td></tr></tbody></table><blockquote><p>The following types are currently supported but will not be supported in TurboModules. Please avoid using them.</p><ul><li>Function (failure) -> RCTResponseErrorBlock</li><li>Number -> NSInteger</li><li>Number -> CGFloat</li><li>Number -> float</li></ul></blockquote><p>For iOS, you can also write native module methods with any argument type that is supported by the <code>RCTConvert</code> class (see <a href="https://github.com/facebook/react-native/blob/master/React/Base/RCTConvert.h" target="_blank" rel="noopener noreferrer">RCTConvert</a> for details about what is supported). The RCTConvert helper functions all accept a JSON value as input and map it to a native Objective-C type or class.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="exporting-constants"></a>Exporting Constants<a aria-hidden="true" tabindex="-1" class="hash-link" href="#exporting-constants" title="Direct link to heading">#</a></h3><p>A native module can export constants by overriding the native method <code>constantsToExport()</code>. Below <code>constantsToExport()</code> is overriden, and returns a Dictionary that contains a default event name property you can access in JavaScript like so:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token operator" style="color:#fc929e">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSDictionary </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">constantsToExport</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">return</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">@"DEFAULT_EVENT_NAME"</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">@"New Event"</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><p>The constant can then be accessed by invoking <code>getConstants()</code> on the native module in JS like so:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> DEFAULT_EVENT_NAME </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">getConstants</span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">log</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">DEFAULT_EVENT_NAME</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>Technically, it is possible to access constants exported in <code>constantsToExport()</code> directly off the <code>NativeModule</code> object. This will no longer be supported with TurboModules, so we encourage the community to switch to the above approach to avoid necessary migration down the line.</p><blockquote><p>Note that the constants are exported only at initialization time, so if you change <code>constantsToExport()</code> values at runtime it won't affect the JavaScript environment.</p></blockquote><p>For iOS, if you override <code>constantsToExport()</code> then you should also implement <code>+ requiresMainQueueSetup</code> to let React Native know if your module needs to be initialized on the main thread, before any JavaScript code executes. Otherwise you will see a warning that in the future your module may be initialized on a background thread unless you explicitly opt out with <code>+ requiresMainQueueSetup:</code>. If your module does not require access to UIKit, then you should respond to <code>+ requiresMainQueueSetup</code> with NO.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="callbacks"></a>Callbacks<a aria-hidden="true" tabindex="-1" class="hash-link" href="#callbacks" title="Direct link to heading">#</a></h3><p>Native modules also support a unique kind of argument - a callback. Callbacks are used to pass data from Objective-C to JavaScript for asynchronous methods. They can also be used to asynchronously execute JS from the native side.</p><p>For iOS, callbacks are implemented using the type <code>RCTResponseSenderBlock</code>. Below the callback parameter <code>myCallBack</code> is added to the <code>createCalendarEventMethod()</code>:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">title</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> myCallback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTResponseSenderBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">callback</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><p>You can then invoke the callback in your native function, providing whatever result you want to pass to JavaScript in an array. Note that <code>RCTResponseSenderBlock</code> accepts only one argument - an array of parameters to pass to the JavaScript callback. Below you will pass back the ID of an event created in an earlier call.</p><blockquote><p>It is important to highlight that the callback is not invoked immediately after the native function completes—remember the communication is asynchronous.</p></blockquote><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">title location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location callback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTResponseSenderBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">callback</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> NSInteger eventId </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">.</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">callback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">[</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">eventId</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">RCTLogInfo</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">@"Pretending to create an event %@ at %@"</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> title</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> location</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><p>This method could then be accessed in JavaScript using the following:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">onSubmit</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'Party'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'04-12-2020'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token parameter">eventId</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">log</span><span class="token punctuation" style="color:#657b83">(</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token template-string string" style="color:#8dc891">Created a new event with id </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">${</span><span class="token template-string interpolation">eventId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">}</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later. This pattern is often used to wrap iOS APIs that require delegates— see <a href="https://github.com/facebook/react-native/blob/3a11f0536ea65b87dc0f006665f16a87cfa14b5e/React/CoreModules/RCTAlertManager.mm" target="_blank" rel="noopener noreferrer"><code>RCTAlertManager</code></a> for an example. If the callback is never invoked, some memory is leaked.</p><p>There are two approaches to error handling with callbacks. The first is to follow Node’s convention and treat the first argument passed to the callback array as an error object.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEventCallback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">title location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location callback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTResponseSenderBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">callback</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> NSNumber </span><span class="token operator" style="color:#fc929e">*</span><span class="token plain">eventId </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">NSNumber numberWithInt</span><span class="token punctuation" style="color:#657b83">:</span><span class="token number" style="color:#5a9bcf">123</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">callback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">[</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">NSNull null</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> eventId</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><p>In JavaScript, you can then check the first argument to see if an error was passed through:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">onPress</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">createCalendarEventCallback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'testName'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'testLocation'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token parameter">error</span><span class="token parameter punctuation" style="color:#657b83">,</span><span class="token parameter"> eventId</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">error</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">error</span><span class="token punctuation" style="color:#657b83">(</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token template-string string" style="color:#8dc891">Error found! </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">${</span><span class="token template-string interpolation">error</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">}</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">log</span><span class="token punctuation" style="color:#657b83">(</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token template-string string" style="color:#8dc891">event id </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">${</span><span class="token template-string interpolation">eventId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">}</span><span class="token template-string string" style="color:#8dc891"> returned</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>Another option is to use two separate callbacks: onFailure and onSuccess.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEventCallback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">title</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> errorCallback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTResponseSenderBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">errorCallback</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> successCallback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTResponseSenderBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">successCallback</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">@try</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> NSNumber </span><span class="token operator" style="color:#fc929e">*</span><span class="token plain">eventId </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">NSNumber numberWithInt</span><span class="token punctuation" style="color:#657b83">:</span><span class="token number" style="color:#5a9bcf">123</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">successCallback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">eventId</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">@catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain"> NSException </span><span class="token operator" style="color:#fc929e">*</span><span class="token plain">e </span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">errorCallback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">e</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><p>Then in JavaScript you can add a separate callback for error and success responses:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">onPress</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">createCalendarEventCallback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'testName'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'testLocation'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token parameter">error</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">error</span><span class="token punctuation" style="color:#657b83">(</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token template-string string" style="color:#8dc891">Error found! </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">${</span><span class="token template-string interpolation">error</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">}</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token parameter">eventId</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">log</span><span class="token punctuation" style="color:#657b83">(</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token template-string string" style="color:#8dc891">event id </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">${</span><span class="token template-string interpolation">eventId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">}</span><span class="token template-string string" style="color:#8dc891"> returned</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><p>If you want to pass error-like objects to JavaScript, use <code>RCTMakeError</code> from <a href="https://github.com/facebook/react-native/blob/master/React/Base/RCTUtils.h" target="_blank" rel="noopener noreferrer"><code>RCTUtils.h.</code></a> Right now this only passes an Error-shaped dictionary to JavaScript, but React Native aims to automatically generate real JavaScript Error objects in the future. You can also provide a <code>RCTResponseErrorBlock</code> argument, which is used for error callbacks and accepts an <code>NSError \* object</code>. Please note that this argument type will not be supported with TurboModules.</p><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="promises"></a>Promises<a aria-hidden="true" tabindex="-1" class="hash-link" href="#promises" title="Direct link to heading">#</a></h3><p>Native modules can also fulfill a promise, which can simplify your JavaScript, especially when using ES2016's <code>async/await</code> syntax. When the last parameter of a native module method is a <code>RCTPromiseResolveBlock</code> and <code>RCTPromiseRejectBlock</code>, its corresponding JS method will return a JS Promise object.</p><p>Refactoring the above code to use a promise instead of callbacks looks like this:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">title</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> resolver</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTPromiseResolveBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">resolve</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> rejecter</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTPromiseRejectBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">reject</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> NSInteger eventId </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token function" style="color:#79b6f2">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">eventId</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">resolve</span><span class="token punctuation" style="color:#657b83">(</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">[</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">eventId</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">reject</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">@"event_failure"</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> </span><span class="token string" style="color:#8dc891">@"no event id returned"</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> nil</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><p>The JavaScript counterpart of this method returns a Promise. This means you can use the <code>await</code> keyword within an async function to call it and wait for its result:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-jsx codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> </span><span class="token function-variable function" style="color:#79b6f2">onSubmit</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">async</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">=></span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">try</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">const</span><span class="token plain"> eventId </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">await</span><span class="token plain"> CalendarModule</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">createCalendarEvent</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'Party'</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token string" style="color:#8dc891">'my house'</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">log</span><span class="token punctuation" style="color:#657b83">(</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token template-string string" style="color:#8dc891">Created a new event with id </span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">${</span><span class="token template-string interpolation">eventId</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:#657b83">}</span><span class="token template-string template-punctuation string" style="color:#8dc891">`</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">catch</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> console</span><span class="token punctuation" style="color:#657b83">.</span><span class="token function" style="color:#79b6f2">error</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">e</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="sending-events-to-javascript"></a>Sending Events to JavaScript<a aria-hidden="true" tabindex="-1" class="hash-link" href="#sending-events-to-javascript" title="Direct link to heading">#</a></h3><p>Native modules can signal events to JavaScript without being invoked directly. For example, you might want to signal to JavaScript a reminder that a calendar event from the native iOS calendar app will occur soon. The preferred way to do this is to subclass <code>RCTEventEmitter</code>, implement <code>supportedEvents</code> and call self <code>sendEventWithName</code>:</p><p>Update your header class to import <code>RCTEventEmitter</code> and subclass <code>RCTEventEmitter</code>:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// CalendarModule.h</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> <React/RCTBridgeModule.h></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> <React/RCTEventEmitter.h></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@interface</span><span class="token plain"> CalendarModule </span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> RCTEventEmitter </span><span class="token operator" style="color:#fc929e"><</span><span class="token plain">RCTBridgeModule</span><span class="token operator" style="color:#fc929e">></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@end</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><p>JavaScript code can subscribe to these events by creating a new <code>NativeEventEmitter</code> instance around your module.</p><p>You will receive a warning if you expend resources unnecessarily by emitting an event while there are no listeners. To avoid this, and to optimize your module's workload (e.g. by unsubscribing from upstream notifications or pausing background tasks), you can override <code>startObserving</code> and <code>stopObserving</code> in your <code>RCTEventEmitter</code> subclass.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token keyword" style="color:#c5a5c5">@implementation</span><span class="token plain"> CalendarManager</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> bool hasListeners</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token comment" style="color:#93a1a1">// Will be called when this module's first listener is added.</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token operator" style="color:#fc929e">-</span><span class="token punctuation" style="color:#657b83">(</span><span class="token keyword" style="color:#c5a5c5">void</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">startObserving </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> hasListeners </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> YES</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token comment" style="color:#93a1a1">// Set up any upstream listeners or background tasks as necessary</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token comment" style="color:#93a1a1">// Will be called when this module's last listener is removed, or on dealloc.</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token operator" style="color:#fc929e">-</span><span class="token punctuation" style="color:#657b83">(</span><span class="token keyword" style="color:#c5a5c5">void</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">stopObserving </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> hasListeners </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> NO</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token comment" style="color:#93a1a1">// Remove upstream listeners, stop unnecessary background tasks</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token operator" style="color:#fc929e">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token keyword" style="color:#c5a5c5">void</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">calendarEventReminderReceived</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSNotification </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">notification</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token plain">eventName </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> notification</span><span class="token punctuation" style="color:#657b83">.</span><span class="token plain">userInfo</span><span class="token punctuation" style="color:#657b83">[</span><span class="token string" style="color:#8dc891">@"name"</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">if</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">hasListeners</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"> </span><span class="token comment" style="color:#93a1a1">// Only send events if anyone is listening</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token keyword" style="color:#c5a5c5">self</span><span class="token plain"> sendEventWithName</span><span class="token punctuation" style="color:#657b83">:</span><span class="token string" style="color:#8dc891">@"EventReminder"</span><span class="token plain"> body</span><span class="token punctuation" style="color:#657b83">:</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">{</span><span class="token string" style="color:#8dc891">@"name"</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain"> eventName</span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="threading"></a>Threading<a aria-hidden="true" tabindex="-1" class="hash-link" href="#threading" title="Direct link to heading">#</a></h3><p>Unless the native module provides its own method queue, it shouldn't make any assumptions about what thread it's being called on. Currently, if a native module doesn't provide a method queue, React Native will create a separate GCD queue for it and invoke its methods there. Please note that this is an implementation detail and might change. If you want to explicitly provide a method queue for a native module, override the <code>(dispatch_queue_t) methodQueue</code> method in the native module. For example, if it needs to use a main-thread-only iOS API, it should specify this via:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token operator" style="color:#fc929e">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">dispatch_queue_t</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">methodQueue</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">return</span><span class="token plain"> </span><span class="token function" style="color:#79b6f2">dispatch_get_main_queue</span><span class="token punctuation" style="color:#657b83">(</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><p>Similarly, if an operation may take a long time to complete, the native module can specify its own queue to run operations on. Again, currently React Native will provide a separate method queue for your native module, but this is an implementation detail you should not rely on. If you don't provide your own method queue, in the future, your native module's long running operations may end up blocking async calls being executed on other unrelated native modules. The <code>RCTAsyncLocalStorage</code> module here, for example, creates its own queue so the React queue isn't blocked waiting on potentially slow disk access.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token operator" style="color:#fc929e">-</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">dispatch_queue_t</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">methodQueue</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token keyword" style="color:#c5a5c5">return</span><span class="token plain"> </span><span class="token function" style="color:#79b6f2">dispatch_queue_create</span><span class="token punctuation" style="color:#657b83">(</span><span class="token string" style="color:#8dc891">"com.facebook.React.AsyncLocalStorageQueue"</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> DISPATCH_QUEUE_SERIAL</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span></div></div></div></div></div><p>The specified <code>methodQueue</code> will be shared by all of the methods in your module. If only one of your methods is long-running (or needs to be run on a different queue than the others for some reason), you can use <code>dispatch_async</code> inside the method to perform that particular method's code on another queue, without affecting the others:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token function" style="color:#79b6f2">RCT_EXPORT_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">doSomethingExpensive</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">param callback</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">RCTResponseSenderBlock</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">callback</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">dispatch_async</span><span class="token punctuation" style="color:#657b83">(</span><span class="token function" style="color:#79b6f2">dispatch_get_global_queue</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">DISPATCH_QUEUE_PRIORITY_DEFAULT</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> </span><span class="token number" style="color:#5a9bcf">0</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> </span><span class="token operator" style="color:#fc929e">^</span><span class="token punctuation" style="color:#657b83">{</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token comment" style="color:#93a1a1">// Call long-running code on background thread</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">.</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token comment" style="color:#93a1a1">// You can invoke callback from any thread/queue</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token function" style="color:#79b6f2">callback</span><span class="token punctuation" style="color:#657b83">(</span><span class="token operator" style="color:#fc929e">@</span><span class="token punctuation" style="color:#657b83">[</span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">.</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">}</span><span class="token punctuation" style="color:#657b83">)</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token punctuation" style="color:#657b83">}</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div></div></div></div></div><blockquote><p>Sharing dispatch queues between modules</p><p>The <code>methodQueue</code> method will be called once when the module is initialized, and then retained by React Native, so there is no need to keep a reference to the queue yourself, unless you wish to make use of it within your module. However, if you wish to share the same queue between multiple modules then you will need to ensure that you retain and return the same queue instance for each of them.</p></blockquote><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="dependency-injection"></a>Dependency Injection<a aria-hidden="true" tabindex="-1" class="hash-link" href="#dependency-injection" title="Direct link to heading">#</a></h3><p>React Native will create and initialize any registered native modules automatically. However, you may wish to create and initialize your own module instances to, for example, inject dependencies.</p><p>You can do this by creating a class that implements the <code>RCTBridgeDelegate</code> Protocol, initializing an <code>RCTBridge</code> with the delegate as an argument and initialising a <code>RCTRootView</code> with the initialized bridge.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">id</span><span class="token operator" style="color:#fc929e"><</span><span class="token plain">RCTBridgeDelegate</span><span class="token operator" style="color:#fc929e">></span><span class="token plain"> moduleInitialiser </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">classThatImplementsRCTBridgeDelegate alloc</span><span class="token punctuation" style="color:#657b83">]</span><span class="token plain"> init</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">RCTBridge </span><span class="token operator" style="color:#fc929e">*</span><span class="token plain">bridge </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">RCTBridge alloc</span><span class="token punctuation" style="color:#657b83">]</span><span class="token plain"> initWithDelegate</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain">moduleInitialiser launchOptions</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain">nil</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">RCTRootView </span><span class="token operator" style="color:#fc929e">*</span><span class="token plain">rootView </span><span class="token operator" style="color:#fc929e">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#657b83">[</span><span class="token punctuation" style="color:#657b83">[</span><span class="token plain">RCTRootView alloc</span><span class="token punctuation" style="color:#657b83">]</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> initWithBridge</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain">bridge</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> moduleName</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain">kModuleName</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> initialProperties</span><span class="token punctuation" style="color:#657b83">:</span><span class="token plain">nil</span><span class="token punctuation" style="color:#657b83">]</span><span class="token punctuation" style="color:#657b83">;</span></div></div></div></div></div><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="exporting-swift"></a>Exporting Swift<a aria-hidden="true" tabindex="-1" class="hash-link" href="#exporting-swift" title="Direct link to heading">#</a></h3><p>Swift doesn't have support for macros, so exposing native modules and their methods to JavaScript inside React Native requires a bit more setup. However, it works relatively the same. Let's say you have the same <code>CalendarModule</code> but as a Swift class:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-swift codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">// CalendarManager.swift</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">@objc(CalendarManager)</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">class CalendarManager: NSObject {</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> @objc(addEvent:location:date:)</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> func addEvent(_ name: String, location: String, date: NSNumber) -> Void {</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> // Date is ready to use!</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> }</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> @objc</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> func constantsToExport() -> [String: Any]! {</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> return ["someKey": "someValue"]</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"> }</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain">}</span></div></div></div></div></div><blockquote><p>It is important to use the <code>@objc</code> modifiers to ensure the class and functions are exported properly to the Objective-C runtime.</p></blockquote><p>Then create a private implementation file that will register the required information with React Native:</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// CalendarManagerBridge.m</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> <React/RCTBridgeModule.h></span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@interface</span><span class="token plain"> </span><span class="token function" style="color:#79b6f2">RCT_EXTERN_MODULE</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">CalendarManager</span><span class="token punctuation" style="color:#657b83">,</span><span class="token plain"> NSObject</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token function" style="color:#79b6f2">RCT_EXTERN_METHOD</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">addEvent</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">name location</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">NSString </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">location date</span><span class="token punctuation" style="color:#657b83">:</span><span class="token punctuation" style="color:#657b83">(</span><span class="token plain">nonnull NSNumber </span><span class="token operator" style="color:#fc929e">*</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain">date</span><span class="token punctuation" style="color:#657b83">)</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain" style="display:inline-block">
|
||
</span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token keyword" style="color:#c5a5c5">@end</span></div></div></div></div></div><p>For those of you new to Swift and Objective-C, whenever you <a href="https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html" target="_blank" rel="noopener noreferrer">mix the two languages in an iOS project</a>, you will also need an additional bridging file, known as a bridging header, to expose the Objective-C files to Swift. Xcode will offer to create this header file for you if you add your Swift file to your app through the Xcode <code>File>New File</code> menu option. You will need to import <code>RCTBridgeModule.h</code> in this header file.</p><div class="mdxCodeBlock_xYIz"><div class="codeBlockContent_rlEb"><button tabindex="0" type="button" aria-label="Copy code to clipboard" class="copyButton_kOW4">Copy</button><div class="prism-code language-objectivec codeBlock_1AP7"><div class="codeBlockLines_1boI" style="color:#FFFFFF;background:#282C34"><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token comment" style="color:#93a1a1">// CalendarManager-Bridging-Header.h</span><span class="token plain"></span></div><div class="token-line" style="color:#FFFFFF;background:#282C34"><span class="token plain"></span><span class="token macro property" style="color:#2aa198">#</span><span class="token macro property directive keyword" style="color:#c5a5c5">import</span><span class="token macro property" style="color:#2aa198"> <React/RCTBridgeModule.h></span></div></div></div></div></div><p>You can also use <code>RCT_EXTERN_REMAP_MODULE</code> and <code>_RCT_EXTERN_REMAP_METHOD</code> to alter the JavaScript name of the module or methods you are exporting. For more information see <a href="https://github.com/facebook/react-native/blob/master/React/Base/RCTBridgeModule.h" target="_blank" rel="noopener noreferrer"><code>RCTBridgeModule</code></a>.</p><blockquote><p>Important when making third party modules: Static libraries with Swift are only supported in Xcode 9 and later. In order for the Xcode project to build when you use Swift in the iOS static library you include in the module, your main app project must contain Swift code and a bridging header itself. If your app project does not contain any Swift code, a workaround can be a single empty .swift file and an empty bridging header.</p></blockquote><h3><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="reserved-method-names"></a>Reserved Method Names<a aria-hidden="true" tabindex="-1" class="hash-link" href="#reserved-method-names" title="Direct link to heading">#</a></h3><h4><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_3pqN" id="invalidate"></a>invalidate()<a aria-hidden="true" tabindex="-1" class="hash-link" href="#invalidate" title="Direct link to heading">#</a></h4><p>Native modules can conform to the <a href="https://github.com/facebook/react-native/blob/0.62-stable/React/Base/RCTInvalidating.h" target="_blank" rel="noopener noreferrer">RCTInvalidating</a> protocol on iOS by implementing the <code>invalidate()</code> method. This method <a href="https://github.com/facebook/react-native/blob/0.62-stable/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm#L456" target="_blank" rel="noopener noreferrer">can be invoked</a> when the native bridge is invalidated (ie: on devmode reload). Please use this mechanism as necessary to do the required cleanup for your native module.</p></div></article><div class="docMetadata margin-vert--xl"><div class="row"><div class="col"><a href="https://github.com/facebook/react-native-website/blob/master/website/versioned_docs/version-0.63/native-modules-ios.md" target="_blank" rel="noreferrer noopener"><svg fill="currentColor" height="1.2em" width="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 40 40" style="margin-right:0.3em;vertical-align:sub"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div><div class="col text--right"><em><small class="docMetadata-updated">Last updated on <time datetime="2021-02-16T18:32:06.000Z" class="docLastUpdatedAt_1gIo">2/16/2021</time></small></em></div></div></div><div class="margin-vert--lg"><nav class="pagination-nav" aria-label="Blog list page navigation"><div class="pagination-nav__item"><a class="pagination-nav__link" href="/docs/native-modules-android"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">« Android Native Modules</div></a></div><div class="pagination-nav__item pagination-nav__item--next"><a class="pagination-nav__link" href="/docs/native-modules-setup"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Native Modules NPM Package Setup »</div></a></div></nav></div></div></div><div class="col col--3"><div class="tableOfContents_3iuQ"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#create-a-calendar-native-module" class="table-of-contents__link">Create a Calendar Native Module</a><ul><li><a href="#setup" class="table-of-contents__link">Setup</a></li><li><a href="#create-custom-native-module-files" class="table-of-contents__link">Create Custom Native Module Files</a></li><li><a href="#module-name" class="table-of-contents__link">Module Name</a></li><li><a href="#export-a-native-method-to-javascript" class="table-of-contents__link">Export a Native Method to JavaScript</a></li><li><a href="#synchronous-methods" class="table-of-contents__link">Synchronous Methods</a></li><li><a href="#test-what-you-have-built" class="table-of-contents__link">Test What You Have Built</a></li><li><a href="#building-as-you-iterate" class="table-of-contents__link">Building as You Iterate</a></li><li><a href="#recap" class="table-of-contents__link">Recap✨</a></li></ul></li><li><a href="#beyond-a-calendar-native-module" class="table-of-contents__link">Beyond a Calendar Native Module</a><ul><li><a href="#better-native-module-export" class="table-of-contents__link">Better Native Module Export</a></li><li><a href="#argument-types" class="table-of-contents__link">Argument Types</a></li><li><a href="#exporting-constants" class="table-of-contents__link">Exporting Constants</a></li><li><a href="#callbacks" class="table-of-contents__link">Callbacks</a></li><li><a href="#promises" class="table-of-contents__link">Promises</a></li><li><a href="#sending-events-to-javascript" class="table-of-contents__link">Sending Events to JavaScript</a></li><li><a href="#threading" class="table-of-contents__link">Threading</a></li><li><a href="#dependency-injection" class="table-of-contents__link">Dependency Injection</a></li><li><a href="#exporting-swift" class="table-of-contents__link">Exporting Swift</a></li><li><a href="#reserved-method-names" class="table-of-contents__link">Reserved Method Names</a></li></ul></li></ul></div></div></div></div></main></div></div><footer class="footer footer--dark"><div class="container"><div class="row footer__links"><div class="col footer__col"><h4 class="footer__title">Docs</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/docs/getting-started">Getting Started</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/tutorial">Tutorial</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/components-and-apis">Components and APIs</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/more-resources">More Resources</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">Community</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/help">The React Native Community</a></li><li class="footer__item"><a class="footer__link-item" href="/showcase">Who's using React Native?</a></li><li class="footer__item"><a href="https://stackoverflow.com/questions/tagged/react-native" target="_blank" rel="noopener noreferrer" class="footer__link-item">Ask Questions on Stack Overflow</a></li><li class="footer__item"><a href="https://github.com/facebook/react-native/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer" class="footer__link-item">Contributor Guide</a></li><li class="footer__item"><a href="https://dev.to/t/reactnative" target="_blank" rel="noopener noreferrer" class="footer__link-item">DEV Community</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">Find us</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/blog">Blog</a></li><li class="footer__item"><a href="https://twitter.com/reactnative" target="_blank" rel="noopener noreferrer" class="footer__link-item">Twitter</a></li><li class="footer__item"><a href="https://github.com/facebook/react-native" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">More</h4><ul class="footer__items"><li class="footer__item"><a href="https://reactjs.org/" target="_blank" rel="noopener noreferrer" class="footer__link-item">React</a></li><li class="footer__item"><a href="https://opensource.facebook.com/legal/privacy" target="_blank" rel="noopener noreferrer" class="footer__link-item">Privacy Policy</a></li><li class="footer__item"><a href="https://opensource.facebook.com/legal/terms" target="_blank" rel="noopener noreferrer" class="footer__link-item">Terms of Service</a></li></ul></div></div><div class="text--center"><div class="margin-bottom--sm"><a href="https://opensource.facebook.com" target="_blank" rel="noopener noreferrer" class="footerLogoLink_19Ac"><img class="footer__logo" alt="Facebook Open Source Logo" src="/img/oss_logo.png"></a></div><div>Copyright © 2021 Facebook, Inc.</div></div></div></footer></div>
|
||
<script src="/styles.cc2cf098.js"></script>
|
||
<script src="/runtime~main.19ca5e97.js"></script>
|
||
<script src="/main.259a8b48.js"></script>
|
||
<script src="/1.55a8a1b3.js"></script>
|
||
<script src="/2.8585ac8b.js"></script>
|
||
<script src="/1f391b9e.8301d553.js"></script>
|
||
<script src="/939.3c971b89.js"></script>
|
||
<script src="/ee5b3385.4adebc95.js"></script>
|
||
<script src="/17896441.6dff1a67.js"></script>
|
||
<script src="/54bb2e43.e2b3c64c.js"></script>
|
||
</body>
|
||
</html> |