For a developer with a strong React Native background, coding in Objective-C or Swift is more time consuming. Fortunately, it’s easy to integrate a React Native view inside an iOS project so you can develop apps using a technology you already know.

This article will focus on the integration specifically for an iOS 10 Messages App/App Extension. App Extensions don't behave exactly the same way as full apps and therefore have some differences in the setup.

The first step is to install Xcode 8. The beta is available here. All the examples will be in Objective-C given that the React Native code base is using Objective-C.

If you want to run on your device directly you will also need to install iOS10 on your phone (usage of the force might be required):

installing iOS10 Beta

Setup the Project (Obj-C)

Create a new iMessage Application project in Xcode, and make sure you select Objective-C as the language.

iMessage Application Project Creation in Xcode 8

You should get a template project with a MessagesViewController.

2. The next step is to use npm to install React and React Native dependencies. To create your initial package.json just run npm init.

Then make sure you add the following script and dependencies.

"scripts": {

"start": "node node_modules/react-native/local-cli/cli.js start"

},

"dependencies": {

"react": "~15.2.0",

"react-native": "^0.30.0"

}

3. Now run npm install.

4. Now that we have the basic dependencies installed we're going to need Cocoa Pods. If you don't want to use Pods you can follow this procedure and jump to step 7 instead. If you don't have Cocoa Pods installed just run sudo gem install cocoapods

5. Now that you have Cocoa Pod installed, we need to create the pod file. To do that, in the same folder as your .xcodeproject, just run pod init.

6. The only pod you need to integrate React Native in your project is the React pod. Since we have that dependency installed from npm, we can just point pods to it. Each part of react-native that you use needs to be specified in the subspecs section. For more information about the subspecs see the React Native documentation. Here is an example with basic support for text images and dev tools:

pod 'React', :path => './node_modules/react-native', :subspecs => [

'Core',

'RCTText',

'RCTNetwork',

'RCTWebSocket',

'RCTImage',

]

Make sure you add that to the MessagesExtension target and not to your main app target.

7. Once this is done, install the pods using pod install. Once the installation complete, close your current Xcode project and open the .xcworkspace that pod just created!

8. Add the React Native minimal App transport security to your project MessagesExtension info.plist. Without this, the development server will not work!

<key>NSAppTransportSecurity</key>

<dict>

<key>NSExceptionDomains</key>

<dict>

<key>localhost</key>

<dict>

<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>

<true/>

</dict>

</dict>

</dict>

Now go in the default MainInterface.storyboard and remove the "Hello Word" that is there by default.

Rendering your first React Native view!

In MessagesViewController.m create a function to render the rootView. Below is an example that we use.

First, there is a function that lazy initializes the bridge. This will run only once when the app starts. The render function will reuse the same bridge every time for performance reasons.

The ReactNative view gets built when the conversation becomes active or when there are transitions to a new presentation style (compact vs expanded). This allows you to pass different props to change what is rendered or to render a different root component (Root components are registered using AppRegistry.registerComponent).

-(void) willBecomeActiveWithConversation:(MSConversation*)conversation {

[super willBecomeActiveWithConversation:conversation]; [self presentReactNativeView:self.presentationStyle];

} -(void) willTransitionToPresentationStyle:(MSMessagesAppPresentationStyle)presentationStyle {

[self presentReactNativeView:presentationStyle];

} -(void) presentReactNativeView:(MSMessagesAppPresentationStyle)presentationStyle {

// If you need you can pass the presentation style to your view

RCTRootView *rootView = [

[RCTRootView alloc] initWithBridge:[self getBridge]

moduleName: @"AmazingMessageExtension"

initialProperties: @{

@"presentationStyle": @(presentationStyle),

}

];

UIViewController *vc = [UIViewController new];

vc.view = rootView; for (UIViewController* cc in self.childViewControllers) {

[cc willMoveToParentViewController:nil];

[cc.view removeFromSuperview];

[cc removeFromParentViewController];

} [self addChildViewController:vc];

vc.view.frame = self.view.bounds;

[self.view addSubview:vc.view]; [vc didMoveToParentViewController:self];

}

static dispatch_once_t once;

static id bridge;

dispatch_once(&once, ^{

NSURL *jsCodeLocation;

#if DEBUG

jsCodeLocation = [NSURL URLWithString:@"

#else

jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

#endif

bridge = [

[RCTBridge alloc] initWithBundleURL:jsCodeLocation

moduleProvider:nil

launchOptions:nil

];

});

return bridge;

} -(RCTBridge*) getBridge {static dispatch_once_t once;static id bridge;dispatch_once(&once, ^{NSURL *jsCodeLocation;#if DEBUGjsCodeLocation = [NSURL URLWithString:@" http://localhost:8081/index.ios.bundle?platform=ios&dev=true "];#elsejsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];#endifbridge = [[RCTBridge alloc] initWithBundleURL:jsCodeLocationmoduleProvider:nillaunchOptions:nil];});return bridge;

Initial Component

Create index.ios.js

import React, { Component } from 'react';

import {

AppRegistry,

StyleSheet,

Text,

ScrollView,

NativeModules,

} from 'react-native'; const styles = StyleSheet.create({

container: {

flex: 1,

backgroundColor: '#F5FCFF',

},

welcome: {

fontSize: 20,

textAlign: 'center',

margin: 10,

},

instructions: {

textAlign: 'center',

color: '#333333',

marginBottom: 5,

},

}); class AmazingMessageExtension extends Component {

render() {

return (

<ScrollView style={styles.container}>

<Text style={styles.welcome}>

Welcome to React Native!

</Text>

<Text style={styles.instructions}>

To get started, edit index.ios.js

</Text>

<Text style={styles.instructions} onPress={() => NativeModules.DevMenu.reload()}>

Press Me to Reload!

</Text>

</ScrollView>

);

}

} AppRegistry.registerComponent('AmazingMessageExtension', () => AmazingMessageExtension);

Running the beast!

Now run npm start and run the project from Xcode! It should build and show you the Hello World!