Files
react-native/docs/nativemodulesios.html
T
2015-05-26 05:24:36 +00:00

108 lines
40 KiB
HTML

<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><title>React Native | A framework for building native apps using React</title><meta name="viewport" content="width=device-width"><meta property="og:title" content="React Native | A framework for building native apps using React"><meta property="og:type" content="website"><meta property="og:url" content="http://facebook.github.io/react-native/index.html"><meta property="og:image" content="http://facebook.github.io/react-native/img/opengraph.png?2"><meta property="og:description" content="A framework for building native apps using React"><link rel="shortcut icon" href="/react-native/img/favicon.png?2"><link rel="stylesheet" href="/react-native/css/react-native.css"><script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script><script type="text/javascript">try{Typekit.load();}catch(e){}</script></head><body><div class="container"><div class="nav-main"><div class="wrap"><a class="nav-home" href="/react-native/"><img src="/react-native/img/header_logo.png">React Native</a><div class="nav-site-wrapper"><ul class="nav-site nav-site-internal"><li><a href="/react-native/docs/getting-started.html" class="active">Docs</a></li><li><a href="/react-native/support.html" class="">Support</a></li></ul><ul class="nav-site nav-site-external"><li><a href="https://github.com/facebook/react-native" class="">GitHub</a></li><li><a href="http://facebook.github.io/react" class="">React</a></li></ul></div></div></div><section class="content wrap documentationContent"><div class="nav-docs"><div class="nav-docs-section"><h3>Quick Start</h3><ul><li><a style="margin-left:0;" class="" href="/react-native/docs/getting-started.html#content">Getting Started</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/tutorial.html#content">Tutorial</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/videos.html#content">Videos</a></li></ul></div><div class="nav-docs-section"><h3>Guides</h3><ul><li><a style="margin-left:0;" class="" href="/react-native/docs/style.html#content">Style</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/gesture-responder-system.html#content">Gesture Responder System</a></li><li><a style="margin-left:0;" class="active" href="/react-native/docs/nativemodulesios.html#content">Native Modules (iOS)</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/nativecomponentsios.html#content">Native UI Components (iOS)</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/linking-libraries.html#content">Linking Libraries</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/debugging.html#content">Debugging</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/testing.html#content">Testing</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/runningondevice.html#content">Running On Device</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/embedded-app.html#content">Integration with Existing App</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/javascript-environment.html#content">JavaScript Environment</a></li></ul></div><div class="nav-docs-section"><h3>components</h3><ul><li><a style="margin-left:0;" class="" href="/react-native/docs/activityindicatorios.html#content">ActivityIndicatorIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/datepickerios.html#content">DatePickerIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/image.html#content">Image</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/listview.html#content">ListView</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/mapview.html#content">MapView</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/navigator.html#content">Navigator</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/navigatorios.html#content">NavigatorIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/pickerios.html#content">PickerIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/scrollview.html#content">ScrollView</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/segmentedcontrolios.html#content">SegmentedControlIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/sliderios.html#content">SliderIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/switchios.html#content">SwitchIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/tabbarios.html#content">TabBarIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/tabbarios-item.html#content">TabBarIOS.Item</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/text.html#content">Text</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/textinput.html#content">TextInput</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/touchablehighlight.html#content">TouchableHighlight</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/touchableopacity.html#content">TouchableOpacity</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/touchablewithoutfeedback.html#content">TouchableWithoutFeedback</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/view.html#content">View</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/webview.html#content">WebView</a></li></ul></div><div class="nav-docs-section"><h3>apis</h3><ul><li><a style="margin-left:0;" class="" href="/react-native/docs/alertios.html#content">AlertIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/appregistry.html#content">AppRegistry</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/appstateios.html#content">AppStateIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/asyncstorage.html#content">AsyncStorage</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/cameraroll.html#content">CameraRoll</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/interactionmanager.html#content">InteractionManager</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/layoutanimation.html#content">LayoutAnimation</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/linkingios.html#content">LinkingIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/netinfo.html#content">NetInfo</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/panresponder.html#content">PanResponder</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/pixelratio.html#content">PixelRatio</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/pushnotificationios.html#content">PushNotificationIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/statusbarios.html#content">StatusBarIOS</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/stylesheet.html#content">StyleSheet</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/vibrationios.html#content">VibrationIOS</a></li></ul></div><div class="nav-docs-section"><h3>Polyfills</h3><ul><li><a style="margin-left:0;" class="" href="/react-native/docs/flexbox.html#content">Flexbox</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/geolocation.html#content">Geolocation</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/network.html#content">Network</a></li><li><a style="margin-left:0;" class="" href="/react-native/docs/timers.html#content">Timers</a></li></ul></div></div><div class="inner-content"><a id="content"></a><h1>Native Modules (iOS)</h1><div><p>Sometimes an app needs access to platform API, and React Native doesn&#x27;t have a corresponding module yet. Maybe you want to reuse some existing Objective-C, Swift or C++ code without having to reimplement it in JavaScript, or write some high performance, multi-threaded code such as for image processing, a database, or any number of advanced extensions.</p><p>We designed React Native such that it is possible for you to write real native code and have access to the full power of the platform. This is a more advanced feature and we don&#x27;t expect it to be part of the usual development process, however it is essential that it exists. If React Native doesn&#x27;t support a native feature that you need, you should be able to build it yourself.</p><p>This is a more advanced guide that shows how to build a native module. It assumes the reader knows Objective-C or Swift and core libraries (Foundation, UIKit).</p><h2><a class="anchor" name="ios-calendar-module-example"></a>iOS Calendar Module Example <a class="hash-link" href="#ios-calendar-module-example">#</a></h2><p>This guide will use the <a href="https://developer.apple.com/library/mac/documentation/DataManagement/Conceptual/EventKitProgGuide/Introduction/Introduction.html" target="_blank">iOS Calendar API</a> example. Let&#x27;s say we would like to be able to access the iOS calendar from JavaScript.</p><p>A native module is just an Objective-C class that implements the <code>RCTBridgeModule</code> protocol. If you are wondering, RCT is an abbreviation of ReaCT.</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// CalendarManager.h
</span>#import <span class="token string">&quot;RCTBridgeModule.h&quot;</span>
@interface <span class="token class-name">CalendarManager</span> <span class="token punctuation">:</span> NSObject &lt;RCTBridgeModule<span class="token operator">&gt;</span>
@end</div><p>In addition to implementing the <code>RCTBridgeModule</code> protocol, your class must also include the <code>RCT_EXPORT_MODULE()</code> macro. This takes an optional argument that specifies the name that the module will be accessible as in your JavaScript code (more on this later). If you do not specify a name, the JavaScript module name will match the Objective-C class name.</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// CalendarManager.m
</span>@implementation CalendarManager
<span class="token function">RCT_EXPORT_MODULE<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
@end</div><p>React Native will not expose any methods of <code>CalendarManager</code> to JavaScript unless explicitly told to. This is done using the <code>RCT_EXPORT_METHOD()</code> macro:</p><div class="prism language-javascript"><span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>addEvent<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>name location<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>location<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">RCTLogInfo<span class="token punctuation">(</span></span>@<span class="token string">&quot;Pretending to create an event %@ at %@&quot;</span><span class="token punctuation">,</span> name<span class="token punctuation">,</span> location<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p>Now, from your JavaScript file you can call the method like this:</p><div class="prism language-javascript"><span class="token keyword">var</span> CalendarManager <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;NativeModules&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">.</span>CalendarManager<span class="token punctuation">;</span>
CalendarManager<span class="token punctuation">.</span><span class="token function">addEvent<span class="token punctuation">(</span></span><span class="token string">&#x27;Birthday Party&#x27;</span><span class="token punctuation">,</span> <span class="token string">&#x27;4 Privet Drive, Surrey&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></div><blockquote><p><strong>NOTE</strong>: JavaScript method names</p><p>The name of the method exported to JavaScript is the native method&#x27;s name up to the first colon. React Native also defines a macro called <code>RCT_REMAP_METHOD()</code> to specify the JavaScript method&#x27;s name. This is useful when multiple native methods are the same up to the first colon and would have conflicting JavaScript names.</p></blockquote><p>The return type of bridge methods is always <code>void</code>. React Native bridge is asynchronous, so the only way to pass a result to JavaScript is by using callbacks or emitting events (see below).</p><h2><a class="anchor" name="argument-types"></a>Argument Types <a class="hash-link" href="#argument-types">#</a></h2><p><code>RCT_EXPORT_METHOD</code> supports all standard JSON object types, such as:</p><ul><li>string (<code>NSString</code>)</li><li>number (<code>NSInteger</code>, <code>float</code>, <code>double</code>, <code>CGFloat</code>, <code>NSNumber</code>)</li><li>boolean (<code>BOOL</code>, <code>NSNumber</code>)</li><li>array (<code>NSArray</code>) of any types from this list</li><li>map (<code>NSDictionary</code>) with string keys and values of any type from this list</li><li>function (<code>RCTResponseSenderBlock</code>)</li></ul><p>But it also works with any 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"><code>RCTConvert</code></a> for details). The <code>RCTConvert</code> helper functions all accept a JSON value as input and map it to a native Objective-C type or class.</p><p>In our <code>CalendarManager</code> example, we need to pass the event date to the native method. We can&#x27;t send JavaScript Date objects over the bridge, so we need to convert the date to a string or number. We could write our native function like this:</p><div class="prism language-javascript"><span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>addEvent<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>name location<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>location date<span class="token punctuation">:</span><span class="token punctuation">(</span>NSNumber <span class="token operator">*</span><span class="token punctuation">)</span>secondsSinceUnixEpoch<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
NSDate <span class="token operator">*</span>date <span class="token operator">=</span> <span class="token punctuation">[</span>RCTConvert NSDate<span class="token punctuation">:</span>secondsSinceUnixEpoch<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p>or like this:</p><div class="prism language-javascript"><span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>addEvent<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>name location<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>location date<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>ISO8601DateString<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
NSDate <span class="token operator">*</span>date <span class="token operator">=</span> <span class="token punctuation">[</span>RCTConvert NSDate<span class="token punctuation">:</span>ISO8601DateString<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p>But by using the automatic type conversion feature, we can skip the manual conversion step completely, and just write:</p><div class="prism language-javascript"><span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>addEvent<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>name location<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>location date<span class="token punctuation">:</span><span class="token punctuation">(</span>NSDate <span class="token operator">*</span><span class="token punctuation">)</span>date<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> // Date is ready to use!
</span><span class="token punctuation">}</span></div><p>You would then call this from JavaScript by using either:</p><div class="prism language-javascript">CalendarManager<span class="token punctuation">.</span><span class="token function">addEvent<span class="token punctuation">(</span></span><span class="token string">&#x27;Birthday Party&#x27;</span><span class="token punctuation">,</span> date<span class="token punctuation">.</span><span class="token function">toTime<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"> // passing date as number of seconds since Unix epoch</span></div><p>or</p><div class="prism language-javascript">CalendarManager<span class="token punctuation">.</span><span class="token function">addEvent<span class="token punctuation">(</span></span><span class="token string">&#x27;Birthday Party&#x27;</span><span class="token punctuation">,</span> date<span class="token punctuation">.</span><span class="token function">toISOString<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"> // passing date as ISO-8601 string</span></div><p>And both values would get converted correctly to the native <code>NSDate</code>. A bad value, like an <code>Array</code>, would generate a helpful &quot;RedBox&quot; error message.</p><p>As <code>CalendarManager.addEvent</code> method gets more and more complex, the number of arguments will grow. Some of them might be optional. In this case it&#x27;s worth considering changing the API a little bit to accept a dictionary of event attributes, like this:</p><div class="prism language-javascript">#import <span class="token string">&quot;RCTConvert.h&quot;</span>
<span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>addEvent<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>name details<span class="token punctuation">:</span><span class="token punctuation">(</span>NSDictionary <span class="token operator">*</span><span class="token punctuation">)</span>details<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
NSString <span class="token operator">*</span>location <span class="token operator">=</span> <span class="token punctuation">[</span>RCTConvert NSString<span class="token punctuation">:</span>details<span class="token punctuation">[</span>@<span class="token string">&quot;location&quot;</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
NSDate <span class="token operator">*</span>time <span class="token operator">=</span> <span class="token punctuation">[</span>RCTConvert NSDate<span class="token punctuation">:</span>details<span class="token punctuation">[</span>@<span class="token string">&quot;time&quot;</span><span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span></div><p>and call it from JavaScript:</p><div class="prism language-javascript">CalendarManager<span class="token punctuation">.</span><span class="token function">addEvent<span class="token punctuation">(</span></span><span class="token string">&#x27;Birthday Party&#x27;</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
location<span class="token punctuation">:</span> <span class="token string">&#x27;4 Privet Drive, Surrey&#x27;</span><span class="token punctuation">,</span>
time<span class="token punctuation">:</span> date<span class="token punctuation">.</span><span class="token function">toTime<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>
description<span class="token punctuation">:</span> <span class="token string">&#x27;...&#x27;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span></div><blockquote><p><strong>NOTE</strong>: About array and map</p><p>Objective-C doesn&#x27;t provide any guarantees about the types of values in these structures. Your native module might expect an array of strings, but if JavaScript calls your method with an array containing numbers and strings, you&#x27;ll get an <code>NSArray</code> containing a mix of <code>NSNumber</code> and <code>NSString</code>. For arrays, <code>RCTConvert</code> provides some typed collections you can use in your method declaration, such as <code>NSStringArray</code>, or <code>UIColorArray</code>. For maps, it is the developer&#x27;s responsibility to check the value types individually by manually calling <code>RCTConvert</code> helper methods.</p></blockquote><h2><a class="anchor" name="callbacks"></a>Callbacks <a class="hash-link" href="#callbacks">#</a></h2><blockquote><p><strong>WARNING</strong></p><p>This section is more experimental than others because we don&#x27;t have a solid set of best practices around callbacks yet.</p></blockquote><p>Native modules also supports a special kind of argument- a callback. In most cases it is used to provide the function call result to JavaScript.</p><div class="prism language-javascript"><span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>findEvents<span class="token punctuation">:</span><span class="token punctuation">(</span>RCTResponseSenderBlock<span class="token punctuation">)</span>callback<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
NSArray <span class="token operator">*</span>events <span class="token operator">=</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token function">callback<span class="token punctuation">(</span></span>@<span class="token punctuation">[</span><span class="token punctuation">[</span>NSNull <span class="token keyword">null</span><span class="token punctuation">]</span><span class="token punctuation">,</span> events<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p><code>RCTResponseSenderBlock</code> accepts only one argument - an array of parameters to pass to the JavaScript callback. In this case we use node&#x27;s convention to make the first parameter an error object (usually <code>null</code> when there is no error) and the rest are the results of the function.</p><div class="prism language-javascript">CalendarManager<span class="token punctuation">.</span><span class="token function">findEvents<span class="token punctuation">(</span></span><span class="token punctuation">(</span>error<span class="token punctuation">,</span> events<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">error<span class="token punctuation">(</span></span>error<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState<span class="token punctuation">(</span></span><span class="token punctuation">{</span>events<span class="token punctuation">:</span> events<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span></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/master/React/Modules/RCTAlertManager.m" target="_blank"><code>RCTAlertManager</code></a> for an example.</p><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"><code>RCTUtils.h</code></a>. Right now this just passes an Error-shaped dictionary to JavaScript, but we would like to automatically generate real JavaScript <code>Error</code> objects in the future.</p><h2><a class="anchor" name="threading"></a>Threading <a class="hash-link" href="#threading">#</a></h2><p>The native module should not have any assumptions about what thread it is being called on. React Native invokes native modules methods on a separate serial GCD queue, but this is an implementation detail and might change. The <code>- (dispatch_queue_t)methodQueue</code> method allows the native module to specify which queue its methods should be run on. For example, if it needs to use a main-thread-only iOS API, it should specify this via:</p><div class="prism language-javascript"><span class="token operator">-</span> <span class="token punctuation">(</span>dispatch_queue_t<span class="token punctuation">)</span>methodQueue
<span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">dispatch_get_main_queue<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p>Similarly, if an operation may take a long time to complete, the native module should not block and can specify it&#x27;s own queue to run operations on. For example, the <code>RCTAsyncLocalStorage</code> module creates it&#x27;s own queue so the React queue isn&#x27;t blocked waiting on potentially slow disk access:</p><div class="prism language-javascript"><span class="token operator">-</span> <span class="token punctuation">(</span>dispatch_queue_t<span class="token punctuation">)</span>methodQueue
<span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token function">dispatch_queue_create<span class="token punctuation">(</span></span><span class="token string">&quot;com.facebook.React.AsyncLocalStorageQueue&quot;</span><span class="token punctuation">,</span> DISPATCH_QUEUE_SERIAL<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p>The specified <code>methodQueue</code> will be shared by all of the methods in your module. If <em>just one</em> 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&#x27;s code on another queue, without affecting the others:</p><div class="prism language-javascript"><span class="token function">RCT_EXPORT_METHOD<span class="token punctuation">(</span></span>doSomethingExpensive<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>param callback<span class="token punctuation">:</span><span class="token punctuation">(</span>RCTResponseSenderBlock<span class="token punctuation">)</span>callback<span class="token punctuation">)</span>
<span class="token punctuation">{</span>
<span class="token function">dispatch_async<span class="token punctuation">(</span></span><span class="token function">dispatch_get_global_queue<span class="token punctuation">(</span></span>DISPATCH_QUEUE_PRIORITY_DEFAULT<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token operator">^</span><span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> // Call long-running code on background thread
</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token comment" spellcheck="true"> // You can invoke callback from any thread/queue
</span> <span class="token function">callback<span class="token punctuation">(</span></span>@<span class="token punctuation">[</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><blockquote><p><strong>NOTE</strong>: 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 the bridge, so there is no need to retain 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; merely returning a queue of the same name for each won&#x27;t work.</p></blockquote><h2><a class="anchor" name="exporting-constants"></a>Exporting Constants <a class="hash-link" href="#exporting-constants">#</a></h2><p>A native module can export constants that are immediately available to JavaScript at runtime. This is useful for communicating static data that would otherwise require a round-trip through the bridge.</p><div class="prism language-javascript"><span class="token operator">-</span> <span class="token punctuation">(</span>NSDictionary <span class="token operator">*</span><span class="token punctuation">)</span>constantsToExport
<span class="token punctuation">{</span>
<span class="token keyword">return</span> @<span class="token punctuation">{</span> @<span class="token string">&quot;firstDayOfTheWeek&quot;</span><span class="token punctuation">:</span> @<span class="token string">&quot;Monday&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></div><p>JavaScript can use this value right away, synchronously:</p><div class="prism language-javascript">console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>CalendarManager<span class="token punctuation">.</span>firstDayOfTheWeek<span class="token punctuation">)</span><span class="token punctuation">;</span></div><p>Note that the constants are exported only at initialization time, so if you change <code>constantsToExport</code> values at runtime it won&#x27;t affect the JavaScript environment.</p><h2><a class="anchor" name="sending-events-to-javascript"></a>Sending Events to JavaScript <a class="hash-link" href="#sending-events-to-javascript">#</a></h2><p>The native module can signal events to JavaScript without being invoked directly. The easiest way to do this is to use <code>eventDispatcher</code>:</p><div class="prism language-javascript">#import <span class="token string">&quot;RCTBridge.h&quot;</span>
#import <span class="token string">&quot;RCTEventDispatcher.h&quot;</span>
@implementation CalendarManager
@synthesize bridge <span class="token operator">=</span> _bridge<span class="token punctuation">;</span>
<span class="token operator">-</span> <span class="token punctuation">(</span>void<span class="token punctuation">)</span>calendarEventReminderReceived<span class="token punctuation">:</span><span class="token punctuation">(</span>NSNotification <span class="token operator">*</span><span class="token punctuation">)</span>notification
<span class="token punctuation">{</span>
NSString <span class="token operator">*</span>eventName <span class="token operator">=</span> notification<span class="token punctuation">.</span>userInfo<span class="token punctuation">[</span>@<span class="token string">&quot;name&quot;</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span>self<span class="token punctuation">.</span>bridge<span class="token punctuation">.</span>eventDispatcher sendAppEventWithName<span class="token punctuation">:</span>@<span class="token string">&quot;EventReminder&quot;</span>
body<span class="token punctuation">:</span>@<span class="token punctuation">{</span>@<span class="token string">&quot;name&quot;</span><span class="token punctuation">:</span> eventName<span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
@end</div><p>JavaScript code can subscribe to these events:</p><div class="prism language-javascript"><span class="token keyword">var</span> subscription <span class="token operator">=</span> DeviceEventEmitter<span class="token punctuation">.</span><span class="token function">addListener<span class="token punctuation">(</span></span>
<span class="token string">&#x27;EventReminder&#x27;</span><span class="token punctuation">,</span>
<span class="token punctuation">(</span>reminder<span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>reminder<span class="token punctuation">.</span>name<span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token comment" spellcheck="true">
// Don&#x27;t forget to unsubscribe, typically in componentWillUnmount
</span>subscription<span class="token punctuation">.</span><span class="token function">remove<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span></div><p>For more examples of sending events to JavaScript, see <a href="https://github.com/facebook/react-native/blob/master/Libraries/Geolocation/RCTLocationObserver.m" target="_blank"><code>RCTLocationObserver</code></a>.</p><h2><a class="anchor" name="exporting-swift"></a>Exporting Swift <a class="hash-link" href="#exporting-swift">#</a></h2><p>Swift doesn&#x27;t have support for macros so exposing it to React Native requires a bit more setup but works relatively the same.</p><p>Let&#x27;s say we have the same <code>CalendarManager</code> but as a Swift class:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// CalendarManager.swift
</span>
@<span class="token function">objc<span class="token punctuation">(</span></span>CalendarManager<span class="token punctuation">)</span>
class <span class="token class-name">CalendarManager</span><span class="token punctuation">:</span> NSObject <span class="token punctuation">{</span>
@objc func <span class="token function">addEvent<span class="token punctuation">(</span></span>name<span class="token punctuation">:</span> String<span class="token punctuation">,</span> location<span class="token punctuation">:</span> String<span class="token punctuation">,</span> date<span class="token punctuation">:</span> NSNumber<span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">&gt;</span> Void <span class="token punctuation">{</span>
<span class="token comment" spellcheck="true"> // Date is ready to use!
</span> <span class="token punctuation">}</span>
<span class="token punctuation">}</span></div><blockquote><p><strong>NOTE</strong>: It is important to use the @objc 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 the React Native bridge:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// CalendarManagerBridge.m
</span>#import <span class="token string">&quot;RCTBridgeModule.h&quot;</span>
@interface <span class="token class-name">RCT_EXTERN_MODULE</span><span class="token punctuation">(</span>CalendarManager<span class="token punctuation">,</span> NSObject<span class="token punctuation">)</span>
<span class="token function">RCT_EXTERN_METHOD<span class="token punctuation">(</span></span>addEvent<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>name location<span class="token punctuation">:</span><span class="token punctuation">(</span>NSString <span class="token operator">*</span><span class="token punctuation">)</span>location date<span class="token punctuation">:</span><span class="token punctuation">(</span>NSNumber <span class="token operator">*</span><span class="token punctuation">)</span>date<span class="token punctuation">)</span>
@end</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"><code>RCTBridgeModule</code></a>.</p></div><div class="docs-prevnext"><a class="docs-next" href="nativecomponentsios.html#content">Next →</a></div></div></section><footer class="wrap"><div class="right">© 2015 Facebook Inc.</div></footer></div><div id="fb-root"></div><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-41298772-2', 'facebook.github.io');
ga('send', 'pageview');
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)
){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
</script></body></html>