Custom Native iOS Views with React Native

    _   _              _    ___  _            _     _                  _
   /_\ | |_ __  ___ __| |_ / _ \| |__ ___ ___| |___| |_ ___   _ _  ___| |_
  / _ \| | '  \/ _ (_-<  _| (_) | '_ (_-</ _ \ / -_)  _/ -_)_| ' \/ -_)  _|
 /_/ \_\_|_|_|_\___/__/\__|\___/|_.__/__/\___/_\___|\__\___(_)_||_\___|\__|
                                                   In Glorious ASCII-VISION
Home

2015-06-26 Fri WARNING: Since I wrote this article new versions of React Native have come out that remove the createReactIOSNativeComponentClass function in favour of requireNativeComponent. I'll try and get this article updated at some point, but until then here's a commit changing to the new method on one of my projects on Github.

2015-04-05 Sun Custom Native iOS Views with React Native

In this post I'm going to show how to create custom native views written in Objective C and integrate them into a React Native application written in JavasScript. It's based on work on I've been doing for Active Inbox (a plugin for Gmail that turns your emails into tasks, you should check it out)

React Native was released by Facebook last week and it's a new way to create native apps on iOS (and soon Android as well) using JavaScript. It differs from PhoneGap/Cordova in that it allows you to create a UI out of real native components, not just an embedded web browser.

Like the React library that it's based on React Native works by specifying views as functions of data. You write code that mostly just assumes that the views will be created anew each time any bit of data changes. The clever bit is that the views aren't actually directly creating UI elements (DOM elements in the case of React, native components in the case of React Native) but are instead creating "Shadow" Views/Elements. React checks these against the previous versions then only updates the bits that have changed.

A simple React Native app looks like this:

React Native comes with a set of built-in components that you can use to create your UI. For a lot of applications these might be sufficient but sometimes you're going to need something custom. Luckily React Native makes it pretty easy to create your own custom native views written in Objective C (or Java presumably once it supports Android) which can then be used just as easily as views written in JavaScript. the process of doing this isn't really documented yet, but the source is available and is pretty clearly written.

To make a custom Objective C view available to React Native you need two Objective C classes: the view itself (which inherits from `UIView` from UIKit) and a React Native View Manager (which inherits from RCTViewManager from React Native). The view can just be a regular iOS view, it doesn't need anything special. The manager has a `view` method that is called by React Native to create an instance of the view. The manager also specifies which properties of the view can be set from the JSX template in JavaScript.

Let's give it a try

We're going to make a simple example view that subclasses `UIView` directly and draws a square that is either red or not red according to an `isRed` property set from the JSX template in JavaScript. We'll be able to use it from JSX template like this:

<MyCustomView
   style={{width: 10, height: 10}}
   isRed={this.state.shouldBeRed}/>

First we create our custom view, in XCode you can select new->file from the File menu then select "Cocoa Touch Class". Call it `MyCustomView` and set the base class to be `UIView`.

Now let's create the View Manager, create another class using XCode but this time call it `MyCustomViewManager` and set the base class to be `RCTViewManager`.

In the `MyCustomViewManager.m` file we just created we need to add an implementation of the `view` method that will return an instance of our custom view.

We want to allow the `isRed` property (which we'll add to our custom view later) to be set. To do this we use a macro that React Native defines in the `RCTViewManager` header file called `RCT_EXPORT_VIEW_PROPERTY`. We can add the following line just above the `view` method definition. This binds the `setRed` property in JSX to the property of the same name on the native view:

We'll also need a couple of extra imports at the top of of the file to allow us to use our custom view and bits from UIKit:

Now let's add the `isRed` poperty to our custom view class implementation in the `MyCustomView.m` file.

And that's all we need on the Objective C side. Let's look at how we hook it up to React Native in JavaScript. The `createReactIOSNativeComponentClass` function can be used to tell React about the Objective C classes we've just written. We'll also need to specify again the properties we want to be able to set (just `isRed` in this case).

We can now use `MyCustomView` just like a regular React Native view class. We can update the `render` method we created earlier to use it:

And that's all there is to it. The example app shown here is on github now.

For more examples I'd recommend looking at the views that come with React Native, they're all implemented in this way so they're a great way of learning how to make your own.

I also just released a HTMLWebView which is custom native view for React Native that let's you display (possibly untrusted) HTML in a UIWebView.

  _______________________________________
< follow me on Twitter: @almostobsolete >
  ---------------------------------------
        \   ^__^
         \  (OO)\_______
            (__)\       )\/\
                 |   | ----w |
                 ||    ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

About me: I'm Tom, a freelance developer in Brighton, UK. You can hire me as a freelancer to write software if you want. I have a portfolio site at tomparslow.co.uk.

About ActiveInbox: ActiveInbox turns Gmail into a task manager, so email becomes the center of your workflow for gettings things done.

Date: 2015-06-26 18:49:30 BST

Author: Thomas Parslow

Org version 7.7 with Emacs version 24