When developing a Titanium mobile app for iOS, learn these best practices so you don't waste time being frustrated with performance and behavior issues.
But developing with Titanium is not the same as for the web -- there are quirks and issues specific to each OS. If you don't know these quirks and don't follow best practices, the end result will likely be disappointing.
This article introduces Titanium's Mobile Best Practices with a short tutorial on writing an iPhone app that presents a table view with custom rows. I assume you have installed Titanium Studio for the Mac after downloading from the Appcelerator Developers site. Registration is free.
Create the demo project
1. Open Titanium Studio and select New | Mobile Project from the File menu.
2. From the available templates, select Classic (Alloy is the other option) and Default Project.
3. Click Next.
4. For project name enter Demo and for the App Id enter com.mycompany.Demo.
5. Click Finish.
A new, classic Titanium mobile project will be created in your chosen workspace location.
In the Editor window, there should be a Dashboard tab (if not, click the little green shield icon in the lower right corner of the Studio next to your name). Find where it says My Apps and click it; Safari will open Appcelerator's web portal for your apps. Click the App Details for your Demo. Figure A shows selections for analytics, cloud, and enterprise extensions, as well as details of your free subscription plan.
Go back to Titanium Studio and double-click the tiapp.xml file in the App Explorer window to display the file in the Editor window (Figure B). Tiapp.xml contains the configuration settings for the Demo app.
If you don't plan to use Appcelerator's analytics service, you should replace true with false between the analytics tags.
The iphone tags contain the orientation settings for the iPhone and the iPad. If you want to add landscape orientation to the iPhone, copy the left and right landscape orientation tags from the iPad section into the iPhone orientations section.
Don't pollute the global object
The main controller for the Demo app is the app.js file. Double-click app.js in the App Explorer window to display the file in the Editor window (Figure C).
Replace the default code with the function shown in the figure. A self-calling function is used to start the application window because it makes a closure that doesn't pollute the global object, available as this in app.js. The function checks the mobile OS name so the application window that has iOS-specific calls to the Titanium SDK is loaded.
Applications should use CommonJS modules
Create the ApplicationWindow.js in the handheld/iphone folder (you may first have to create the handheld and iphone folders). Display the file in the Editor window. The file shown in Figure D contains a module for instantiating an iOS navigation window object. The navigation window’s initial window is loaded from the TableWindow.js file. The module is exposed to the outside world with the exports directive.
The table view
Create the TableWindow.js file in the handheld/iphone folder and display the file in the Editor window. The file shown in Figures E and F contains a module for instantiating a window containing a table view.
Each row of the table view is created with the createTableViewRow API so it can be customized. For iOS, it is important to explicitly set the row's height (do not use 'auto' or Ti.UI.SIZE) and className properties for all rows that have the same layout.
It is also important to create a transparent view that fills the entire row. With the touchEnabled property of the row set to false, the transparent view will capture all single tap events. Otherwise, the table will capture the single tap events and the event will not include the tapped row’s index.
Add a listener for single tap events to the table. Only one listener is needed for all the rows (do not add a listener to each row or the button in each row). Because the table, row, transparent row view, and button each have an objName property, it will be included with the event's source property. If the objName is 'button', a dialog is shown with the button title. Otherwise, the Detail Window is loaded and opened in the navigation window. This window is loaded only when a row is tapped.
The Detail window
Create the DetailWindow.js file in the handheld/iphone folder and display the file in the Editor window. The file shown in Figure G contains a module for instantiating a window with a label that displays the index of the row that was tapped.
Best practices for managing memory include closing windows, nulling out references to objects, and removing global event handlers when no longer used. It is also easy to create a memory leak by adding an event handler to a UI object (e.g., a table) in a scope other than where the object is declared. For example, it’s bad to declare a table outside of a module's exported function and add an event handler to the table within that function.
Run the app
Assuming you have the Xcode tools installed and have added a launch configuration for the iPhone simulator to the Demo project, it is easy to run the simulator, or install onto a device, from Titanium Studio.
In the App Explorer window, click the Run icon and select the iPhone simulator launch configuration. The first screen shot below shows the Demo app after the button labeled H is tapped. The second screen shot below shows the detail window after the row is tapped.
This simple demo app is hopefully something you can build upon when developing a more complex Titanium mobile app. In addition to the best practices, you should keep up to date with the tips, tricks, and gotchas found in the forums and on developer blogs. Titanium is always improving, and Alloy is the next thing to consider.
Additional reading about Titanium
- Mobile Best Practices
- Appcelerator Blog
- Learning Titanium
- Appcelerator Developer Center
- Titanium tips and tricks thread
- Titanium Mobile - Gotchas
- About the Debug Perspective