Hyperloop: Working with Native Controls in iOS

In this post we’re going to give you a quick introduction to Hyperloop by adding an iOS UIButton to a Titanium Alloy project and adding a click event handler. We’ll be writing code in JavaScript and using Hyperloop to access the underlying iOS SDK, working directly with the UIKit/UIButton class.

We’re focusing this example on iOS and we’ll post a follow-up for Android — we’ll also post the full source-code to our Hyperloop Samples.

(This post assumes you’ve created a new Alloy project with the 5.4.0.GA SDK and added Hyperloop support. You can find out more here.)

Let’s get started.

In order to access native objects with Hyperloop, you have to require the relevant libraries you’ll need in your project. If you’re familiar with Objective-C or Swift, this is essentially the same as using the Import keyword.

Since we’re going to be working with UIButton, we need to include the relevant class we need, namely UIKit/UIButton.

We also need access to constants (UIControlStateNormal), and the UIColor and CGRectMake classes, for color setting and drawing.

In your Index.js controller, create the following code:

var UIButton = require('UIKit/UIButton'),
UIControlStateNormal = require('UIKit').UIControlStateNormal,
UIControlStateSelected = require('UIKit').UIControlStateSelected,
UIControlEventTouchUpInside = require('UIKit').UIControlEventTouchUpInside,
UIColor = require('UIKit/UIColor'),
CGRectMake = require('CoreGraphics').CGRectMake

This creates the relevant links to the underlying SDK classes and constants we need — next let’s create an instance of UIButton:

var button = new UIButton();

Now let’s give it some color, shape and content. As this is a native UIButton, we need to use the underlying SDK methods and properties to do that:

button.backgroundColor = UIColor.blueColor();
button.layer.cornerRadius = 6;
button.frame = CGRectMake(50, 50, 300, 100);
button.setTitleForState('CLICK ME', UIControlStateNormal);

In this block of code, we’ve done a few things; we’ve set the colour to blue using IUColor.blueColor(), we’ve set what we’d normally call a borderRadius in Titanium by setting cornerRadius, and we’ve defined the shape and position of our button using CGRectMake(x,y,width,height).

The final task is to set the button title, using the method setTitleForState and passing a string and a constant (remember that require from earlier) for UIControlStateNormal.

The final step is to actually add the button to the view / window — so assuming you’re using Alloy and have created a view with a Window, you would do this with a normal .add method, but wait — first we need to add some events.

Typically in Titanium, we’d have access to object.addEventListener() but that won’t work here (at least not yet), so we need to work a slightly different way. In iOS, you normally handle events using a delegate; an object that can handle the control requests for an element, and respond to them.

In our case, we need to create a new delegate class that will respond to the click event of our button, so let’s do that — firstly we need to define a custom class in Hyperloop.

(Make sure you move the $.getView.add(button) line to below the rest of this code coming up)

var ButtonDelegate = Hyperloop.defineClass('ButtonDelegate', 'NSObject');

This creates a new class in Hyperloop that exists on the native side as ‘ButtonDelegate‘ and on the JavaScript side it’s been assigned to the variable ButtonDelegate.

Next, we need to create a method against this class that will handle the button click event. We can define methods like this:

    selector: 'buttonPressed:',
    instance: true,
    arguments: ['UIButton'],
    callback: function(sender) {
        if (this.buttonPressed) {

We’ve now defined a native class in Hyperloop and added a new method to it to handle our button press.

Next, we need to create an instance of our new delegate and set the .buttonPressed method to be our callback function:

var delegate = new ButtonDelegate();
delegate.buttonPressed = function(sender) {
    alert('button pressed!');

Almost there — next we need to tell the UIButton that we want our delegate to respond to all control events:

button.addTargetActionForControlEvents(delegate, 'buttonPressed:', UIControlEventTouchUpInside);

This basically routes all control events for the button through our delegate class — we could add more methods to it later to respond to different types of control events but for now we’re just focusing on the click event.

Finally we need to add the native button to the view, which in Alloy is as easy as:


That’s it — run the project, click the button, and you’ve just interacted with a native UIButton on a Titanium View.

So, what more can you do with this?

Because Hyperloop can work seamlessly with Titanium code, you can have this button manipulate other elements that are written in Hyperloop or Titanium, you could add more native elements like UILabel, or you could access iOS specific properties of UIButton that aren’t available in the Titanium SDK.

Extend this to other UIKit components and you can create Labels, TableViews — anything you want, and add these to a Titanium project — you can even wrap these in CommonJS modules to create custom Alloy Tags.

We hope you found this basic intro useful, and we’ll be adding much more content with more advanced examples and covering other SDK. In the meantime, be sure to check out the Hyperloop Samples for more examples of how to work with Hyperloop!

Code strong! ?