Skip to content

Instantly share code, notes, and snippets.

@kwhinnery
Last active August 29, 2015 13:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kwhinnery/9399280 to your computer and use it in GitHub Desktop.
Save kwhinnery/9399280 to your computer and use it in GitHub Desktop.

Embedded Titanium

Hi Jeff and Tony! Here's the getting started guide for the fantasy Titanium component I want you to build for me :)

About Embedded Titanium

Embedded Titanium allows native iOS developers to rapidly build part or all of their mobile application using simple JavaScript APIs. Use a TitaniumViewController just like you would a UIViewController in your iOS app to mix and match pure native views and JavaScript-driven Titanium views. It's less filling AND it tastes great!

Installation

Embedded Titanium is distributed through Cocoapods. To install, add the following to your Podfile:

pod Titanium

...and install with pod install.

Basic Usage

Open your iOS application's App Delegate implementation file, <Your App Prefix>AppDelegate.m, and add the Titanium headers:

#import "Titanium.h"

In application:didFinishLaunchingWithOptions:, let's create and display a simple Titanium-powered view controller. Replace that method with the following:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    TitaniumViewController *mainViewController = [TitaniumViewController alloc] initWithScript@"index.js"];
    
    self.window.rootViewController = mainViewController;
    [self.window makeKeyAndVisible];
    return YES;
}

You'll notice that when we initialize the TitaniumViewController, we pass in the name of a JavaScript file named index.js. This file should exist within the application's bundle, and will be loaded to drive the behavior of the Titanium view. In Xcode, create a new file named index.js with the following contents:

var window = Ti.UI.createWindow({ backgroundColor:'red' }),
    label = Ti.UI.createLabel({ text:'hello world' });
    
window.add(label);

window.open();

In practice, you'll probably want to edit your JavaScript in an external editor, since the JavaScript support in Xcode blows. But for now, feel free to edit this file directly in Xcode.

Now, run the project in Xcode. You should see a red screen with a label in the center reading "hello world".

Awesome! You just created a native UI in JavaScript, in a fraction of the code that would be necessary to do this programmatically in Objective-C. But what if I want or need to use native UI alongside my JavaScript? Fear not, using Embedded Titanium, this is super easy!

Using Titanium Alongside Native UI

Let's say that we want to create a smooth sliding menu using an awesome community-created UI component, PKRevealController. But instead of writing native code to drive the menu and content views, we want to use JavaScript-driven Titanium views. No problemo - you would just do the following, after installing PKRevealController from Cocoapods and including the header:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    // Create main app interface
    TitaniumViewController *mainViewController = [TitaniumViewController alloc] initWithScript@"index.js"];
    TitaniumViewController *menuViewController = [TitaniumViewController alloc] initWithScript@"menu.js"];
    PKRevealController *revealController = [PKRevealController revealControllerWithFrontViewController:mainViewController
                                                                                    leftViewController:menuViewController];
    
    // Create main app window
    self.window.rootViewController = revealController;
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

...and in a new file called menu.js....

var window = Ti.UI.createWindow({ backgroundColor:'green' }),
    label = Ti.UI.createLabel({ text:'i am the slidey menu' });
    
window.add(label);

window.open();

Now, when you run the Xcode project, you should be able to swipe left and right to reveal two Titanium controlled views!

Communicating with the Titanium Views

Now periodically, it stands to reason you would need to send data back and forth between the JS-driven views and native code. There's a few ways to do this, but the simplest is to define a block of code that will be called when an event is fired by JavaScript code:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    // Create main app interface
    TitaniumViewController *mainViewController = [TitaniumViewController alloc] initWithScript@"index.js"];
    TitaniumViewController *menuViewController = [TitaniumViewController alloc] initWithScript@"menu.js"];
    PKRevealController *revealController = [PKRevealController revealControllerWithFrontViewController:mainViewController
                                                                                    leftViewController:menuViewController];
                                                                                    
    // Listen for an event fired by JS
    [mainViewController listenForEvent:@"customEvent" withBlock:^(id event) {
        NSDictionary *dict = (NSDictionary*) event;
        NSLog(@"got this from JS: %@", [dict valueForKey:@"message"]);
    }];
    
    // Create main app window
    self.window.rootViewController = revealController;
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

...and then in index.js...

var window = Ti.UI.createWindow({ backgroundColor:'red' }),
    label = Ti.UI.createLabel({ text:'hello world' });
    
window.add(label);

label.addEventListener('click', function(e) {
    Ti.App.fireEvent('customEvent', { message: 'hooray for JavaScript!' });
});

window.open();

Now when you run the project and tap the label in the main view, a log message is created in Xcode with the data you sent from JavaScript. Going the other way is just as easy. Native code:

[mainViewController fireEvent:@"nativeGeneratedEvent" withData:@{@"foo": @"bar"}];

JS code to listen...

Ti.App.addEventListener('nativeGeneratedEvent', function(e) {
    alert('foo was: ' + e.foo);
});

Embedding Native UI

What if you need to embed a native UI control in a JavaScript-driven UI? It's all good in the hood - just give Titanium the name of the UIViewController subclass you want to insert in the UI:

var nativeView = Ti.UI.createNativeView({
    className:'KEVFakeViewController'
});

someJavaScriptView.add(nativeView);

Conclusion

With Embedded Titanium, you can rapidly prototype, build, and deploy interactions with JavaScript, while retaining 100% of the power and flexibility of the native toolchain. Titanium not cutting it for some performance-critical piece of the app? Don't throw the baby out with the bath water - refactor what you need into native code, but retain the awesomeness of JS for everything else.

We hope you love using Embedded Titanium!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment