PhoneGap, Appcelerator and mobile web frameworks

What are mobile web frameworks

What are web based application frameworks? First, there are many out there including PhoneGap, Appcelerator, etc. For developers struggling to learn Objective-C, Java, etc these frameworks allow you to still build mobile applications. Essentially, these frameworks exist to help developers that come from a web development background with a set of tools to use with their current skillset (HTML, CSS and Javascript) to build native or native-like mobile applications. PhoneGap and Appcelerator Titanium are the most popular amongst all the frameworks out there on the interweb. For this blog post, I want to compare and contrast the two along with other mobile frameworks. Hopefully this will help you if you’re deciding on which framework to architect your next project.

PhoneGap is developed by Nitobi Software which was recently acquired by Adobe. On their website, it says “Build apps in HTML and Javascript and still take advantage of core features in iPhone/iPod touch, iPad, Google Android, Palm, Symbian and Blackberry SDKs.” Currently, PhoneGap v1.3 supports 7 different platforms including iOS, Android, Palm, WebOS, WP7, Symbian and Bada. The framework is open source which means developers and companies can use PhoneGap for mobile applications that are free, commercial, open source, or any combination of these.

What is required to use PhoneGap

PhoneGap projects require the underlying SDKs (e.g. iOS 5 SDK) to be installed and building the project happens from an IDE, such as Xcode 4. Once you have Xcode and iOS 5 SDK installed, download PhoneGap and install it. Open up Xcode and under the New Project dialog, there should be a PhoneGap-based Application project template as shown in Figure 1.

New Project Dialog

Figure 1

After installing the PhoneGap project template, make sure to build and launch the iPhone simulator. You should see an error in your simulator informing your “index.html” was not found as shown in Figure 2.

iPhone Simulator Error

Figure 2

In order to fix this, go ahead and copy the ‘www’ directory to the Project Navigator in Xcode. The ‘www’ folder exists in the PhoneGap project folder location. You can quickly go to that folder by right-clicking on the project root in Project Navigator and selecting “Show In Finder”. After you drag the ‘www’ folder, you should see a prompt as shown in Figure 3. Select “Create folder references for any added folders” and click Finish.

Folder Reference

Figure 3

Your Project Navigator should look similar to Figure 4.

Project Navigator

Figure 4

Now rebuilt and run the iPhone simulator again and you should see similar to Figure 5

iPhone Simulator

Figure 5

Basically, the developer puts his files (HTML, CSS or Javascript) into a ‘www’ folder in the project directory. When building, PhoneGap then renders these files inside a native WebView provided by the OS-specific language (either Objective-C or Java), it exposes access to certain native device features, like Accelerometer, Camera, Notifications, etc.

In a nutshell, a PhoneGap application is essentially still a web application, wrapped inside a WebView. It still remains a web application that is displayed through rendering of HTML, CSS and Javascript using a browser instance on a mobile device.

Appcelerator Titanium

Appcelerator Titanium is another mobile framework to help developers build mobile applications but only on iOS and Android at this time. Similar to PhoneGap, Titanium provides a binding layer that maps Javascript function calls to natively available APIs.

However, Appcelerator claims to be different than PhoneGap in translating Javascript code to native application code. The Javascript code is being interpreted during runtime and through a bridge layer, function calls to Titanium.some_function invoke native application code under the hood.

Another way Appcelerator is different is up until the latest version of Appcelerator, v1.5, you would write your application code in HTML, CSS and Javascript. Now, the application code is written in pure Javascript, using mainly functions that the Titanium API exposes. Apart from using it to access special device features (Camera, Accelerometer, etc), it also enables the developer to render native UI elements (buttons, tables, etc).

These differences give Appcelerator an edge of performance. Just want to emphasize, all the application code will be in Javascript, even the styling of elements happens through function calls. One thing to also keep in mind is to ask yourself will the Javascript API provide all the functionality needed in your application.

Unlike PhoneGap, building and packaging your application does not happen inside an IDE (Xcode, Eclipse, etc), but through their software, Titanium Developer. This is the tool to set up new projects, configure, test and package them. Any IDE of your choice can be used to write the application code.

When choosing a mobile web framework, keep in mind it depends on the requirements of the application when choosing which framework to go with. If the goal is to target many platforms as possible, then PhoneGap may be the right choice. If true native-ness and performance is important, then Titanium may be the choice.

There are many other mobile web frameworks out there that are open source and free and some that charge a developers license fee. I would like to write a follow up blog post on MonoTouch, NimbleKit, AppMobie and others. Stay tuned.

Introduction to iOS 5 Storyboards Part 2

Passing Data from One Screen to Another

This post continues from How To Use iOS 5 Storyboard Part 1 and uses the same project, StoryboardSample. Right now we have a two view controllers in our storyboard. When a user clicks on the button, the screen navigates to the second controller. Now we want to pass data from one scene to another using storyboards.

Passing Data From One Screen to Another

When a transition is happening from one scene to another, the storyboard runtime creates a segue object for that transition. A segue is an Objective-C object. It is an instance of class UIStoryboardSegue. A segue is represented in the Storyboard canvas.

When a transition happens, the current view controller will receive the prepareForSegue:sender: message where the prepareForSegue parameter will be an object of type UIStoryboardSegue. If you want to pass any data from the current view controller to view controller which is about to appear on the screen, you need to do that in the prepareForSegue:sender: method.

1. Add the following prepareForSegue:sender: method in the first view controller:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSLog(@"Source Controller = %@", [segue sourceViewController]);
    NSLog(@"Destination Controller = %@", [segue destinationViewController]);
    NSLog(@"Segue Identifier = %@", [segue identifier]);
}

If you run this app now, you will see the results in the console window. However, the identifier variable is nil. Each segue has an identifier which can uniquely identify that segue.

Since one scene can have more than one segue associated with it, it is good to give your segues identifiers that you can then detect in your view controllers and take action accordingly.

A segue object in IB is the connection between two scenes as shown in Figure 1.

Segue arrow

Figure 1

Follow these steps to give your segue an identifier:

1. Select your segue object in IB
2. From the View menu, select Utilities->Show Attributes Inspector
3. In the Attributes Inspector, in the Identifier text field, write text for the identifier value for this segue. I named the identifier, SegueId1. Press Enter.

Also, add a second view controller to the project navigator. Follow the following steps to add a view controller to your existing project.

1, Go to File -> New -> New File. A New File dialog should appear as shown in Figure 2

Add New File dialog

Figure 2

2. Select Cocoa Touch under iOS on the left side and then select UIViewController subclass on the right.
3. Click Next and enter a Class name, I chose SecondViewController. Leave Targed for iPad and With XIB for user interface unchecked as shown in Figure 3

Name View Controller

Figure 3

4. Choose a folder to save new file and click Create button.

Your project navigator should contain similar files as shown in Figure 4

Project Navigator Files

Figure 4

You can see that when the storyboard runtime calls the prepareForSegue:sender: method in the current view controller to prepare it for the segue, the destination view controller has already been initialized in the segue object. Now this is your chance to pass any required data to the destination view controller, SecondViewController.

You can either set the data directly into a property of the destination view controller or pass your data by calling a method on that view controller. Below is the updated code to pass data from the first view controller to the second view controller. Add an import statement at the top of the implementation file of your first view controller to reference the second view controller as shown in Figure 5.

Import Statement

Figure 5

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSLog(@"Source Controller = %@", [segue sourceViewController]);
    NSLog(@"Destination Controller = %@", [segue destinationViewController]);
    NSLog(@"Segue Identifier = %@", [segue identifier]);

    if ([[segue identifier] isEqualToString:@"SimpleSegueToSecondViewController"])
    {
        SecondViewController *viewController = [segue destinationViewController];
        //viewController.dataModel = ...
    }
}


Adding a Storyboard to an Existing Project

If you already have an existing project where you navigate between screens manually and you want to start using storyboards, I will show how to take advantage of them with the below steps. The structure of project apps that use storyboards are different than project apps that do not. For once, the storyboard-based apps no longer use a main nib file for their windows. This needs to be removed from the .plist of our app. Also, when updating an old app to now use storyboards, you will need to make the app understand what storyboard files are by setting them in the .plist.

The last step below mentions to make sure that the app delegate in your app is not messing with how we are intending to load our storyboards. All apps are different, but you have to make sure that the app delegate is not assigning any object to the rootViewController property of the window. If it does, your storyboards will not be displayed and you will spend time trying to find out what the issue is.

1. From the File menu, choose New->New File
2. In the New File dialog, make sure you have selected User Interface under iOS on the left side and select Storyboard on the right.
3. Click Next to move to the next screen.
4. In this screen, pick the Device Family for which you want to create your storyboard. If your app is an iPhone or iPad only app, then pick the appropriate device family. If your app is a universal app, you will need to select one device family now, create the storyboard file and then come back and create another one for your other device family. Then press the Next button.
5. Now select where to save your storyboard file.
6. In the Project Navigator in Xcode, find the *Info.plist file. Note that this *.plist file might have been stored under a different name depending on the name of your project. Once you click on this file, the property list editor will open automatically as shown in Figure 6

Plist Editor

Figure 6

7. If you have any of the following keys, delete them from the *plist file: NSMainNibFile and NSMainNibFile~ipad
8. If you have an iPhone or iPad only app, then create a new key called UIMainStoryboardFile for iPHone or UIMainStoryboardFile~ipad for iPad. If you have a universal app, create both these keys.
9. For the value of these keys, provide the filename of the storyboards that you created without the .storyboard extension.
10. Make sure to save the .plist file.
11. Remove the application:didFinishLaunchingWithOptions: method from your app delegate’s implementation. Usually in this method, you write logic to set up different view controllers and windows and etc. With storyboards, you will no longer need this. At the very least, just remove the logic code in this method if you have any other code inside that remains relevant.