Extending Titanium Mobile through Native Modules Olivier Morandi
# whoami Olivier Morandi Freelance mobile developer & software engineer [email_address] @olivier_morandi https://github.com/omorandi
Titanium Mobile A set of tools for developing cross-platform mobile applications in JavaScript iOS (iPhone/iPod/iPad)  Android  Blackberry (through a commercial subscription) http://www.appcelerator.com https://github.com/appcelerator/titanium_mobile
Anatomy of a project Project directory build/ android/ iphone/ Resources/ app.js manifest tiapp.xml Project files Resource files: JS code, images, sounds, Sqlite DBs, etc. Build folders, per platform
manifest #appname: whymca #publisher: olivier #url: http://www.whymca.org #image: appicon.png #appid: com.whymca.test #desc: undefined #type: mobile #guid: 746e9cb4-49f6-4afe-af0b-5de9f0116f65
tiapp.xml <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?> <ti:app xmlns:ti=&quot;http://ti.appcelerator.org&quot;> <deployment-targets> <target device=&quot;iphone&quot;>true</target> <target device=&quot;ipad&quot;>false</target> <target device=&quot;android&quot;>true</target> </deployment-targets> <id>com.whymca.test</id> <name>whymca</name> <version>1.0</version> <publisher>olivier</publisher> <url>http://www.whymca.org</url> <description>not specified</description> <copyright>2011 by olivier</copyright> <icon>appicon.png</icon> <persistent-wifi>false</persistent-wifi> <prerendered-icon>false</prerendered-icon> <statusbar-style>default</statusbar-style> <statusbar-hidden>false</statusbar-hidden> <fullscreen>false</fullscreen> <navbar-hidden>false</navbar-hidden> <analytics>false</analytics> <guid>746e9cb4-49f6-4afe-af0b-5de9f0116f65</guid> <iphone> <orientations device=&quot;iphone&quot;> <orientation>Ti.UI.PORTRAIT</orientation> </orientations> <orientations device=&quot;ipad&quot;> <orientation>Ti.UI.PORTRAIT</orientation> <orientation>Ti.UI.UPSIDE_PORTRAIT</orientation> <orientation>Ti.UI.LANDSCAPE_LEFT</orientation> <orientation>Ti.UI.LANDSCAPE_RIGHT</orientation> </orientations> </iphone> <android xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;> </android> <modules> </modules> </ti:app>
app.js (1) var win = Titanium.UI.createWindow({  title: 'Hello' , backgroundColor: '#fff' }); var label1 = Titanium.UI.createLabel({ color: '#333' , text: ’Hello World!' , textAlign:  'center' , font: {fontSize: 30, fontWeight:  'bold' } }); win. add (label1);
app.js (2) var bt = Titanium.UI.createButton({ title:  'Click me' ,  width: 100, height: 40, bottom: 40 }) bt.addEventListener( 'click' ,  function (e) { label1.text =  'WHYMCA ROCKS!' ; }); win. add (bt); win. open ();
UI widgets created in JS are mapped on the native components of the target platform
App distribution The product ready for distribution is actually a native app JS Code Partially compiled and optimized Packed in binary format into the bundle Resources Copied into the bundle
Development toolchain Ti Developer (toolchain GUI) Ti Studio (IDE) Ti SDK toolchain (Python scripts) Mac OSX Mac OSX Windows Linux Xcode/iOS SDK Android SDK
Application Stack JavaScript Application Code Titanium JavaScript API Android  Modules iOS  Modules Android SDK iOS SDK Titanium Framework JS Interpreter Runtime JS Interpreter Runtime
Ti JavaScript API http://developer.appcelerator.com/apidoc/mobile
Extending the API: why? Accessing specific OS features Leveraging existing native libraries Optimizing critical portions of the app Extending/ameliorating portions of the Titanium Mobile framework
Extending the API: how? Creating a fork of Titanium Mobile’s source code on github Unflexible approach You put your hands in the heart of the framework Maintaining a separate branch can be tedious and costly There are situations where this is the cheaper approach E.g. when needing to extend the functionality of core modules of the framework (networking, maps, ecc.)
Extending the API: how? Creating one or more native modules throught the Titanium Module SDK Great flexibility Easy to distribute as Open Source Binary packages Appcelerator Ti+Plus Marketplace (?)
Moduli nativi – some examples Android barcode scanner (Zxing wrapper) https://github.com/mwaylabs/titanium-barcode iOS ZipFile (create/decompress zip files) https://github.com/TermiT/ZipFile iOS TiStoreKit (in app purchase) https://github.com/masuidrive/TiStoreKit iOS TiSMSDialog (in app sms sending) https://github.com/omorandi/TiSMSDialog Appcelerator Titanium modules (sample modules) https://github.com/appcelerator/titanium_modules
Titanium JS Interface var bt = Titanium.UI.createButton({ title:  'Click me' ,  width: 100, height: 40, bottom: 40 }); bt.addEventListener( 'click' ,  function (e) { label1.text =  'WHYMCA ROCKS!' ; });
Titanium JS Interface Module Titanium.UI Object Titanium.UI.Button Object Factory Titanium.UI.createButton() Property getters/setters - methods Button.title Button.width Button.animate() Ecc. Event handling Button.addEventListener()
Module Architecture Titanium.UI Titanium.UI.Button Titanium.UI.Button.width Module Proxy Internal State setters/getters Methods Events Module Class Namespace Object Object property/method Proxy Class  Implementation Titanium  abstraction JavaScript Factory Internal State setters/getters Methods Events
The path to module development Define the functionality you need to be exposed and how they’ll be invoked from JavaScript code    define the API of the module Create a project with the tools of the Module SDK Implement the API Build-Test-Debug
Case Study – iOS SMS module The Titanium API provides email sending functionality through the Ti.UI.EmailDialog component, but nothing for sending SMS messages On iOS this feature is available since version 4.0 of the OS through the  MFMessageComposeViewController  class
MFMessageComposeViewController
Case Study – iOS SMS module Implement a native module capable of exposing the features of the  MFMessageComposeViewController  class through a JavaScript API: Check the availability of the component (not present in iOS versions < 4.0) Programmatically set recipients and message body Set UI properties (e.g. navbar color) Notify the caller about the result of the send operation
Resources Module SDK Docs Android http://wiki.appcelerator.org/display/guides/Module+Developer+Guide+for+Android iOS http://wiki.appcelerator.org/display/guides/Module+Developer+Guide+for+iOS Titanium Mobile source code https://github.com/appcelerator/titanium_mobile Code of other modules released as open source
1. Defining the API Object SMSDialog Properties recipients messageBody barColor Methods isSupported() open()
Example code var  smsDialog = module.createSMSDialog(); if  (smsDialog.isSupported())  { smsDialog.recipients = [ ’+14151234567' ]; smsDialog.messageBody =  'Test message from me' ; smsDialog.barColor =  ’red' ; smsDialog.addEventListener( 'complete' ,  function (e){ Ti.API.info( 'Result: '  + e.resultMessage); }); smsDialog.open({animated: true}); }
Result
2. Creating the project # titanium create  --platform= iphone  --type= module  --dir= ~/ --name= SMSDialog  --id= com.whymca.smsdialog
titanium (alias) Mac OS X alias titanium=&quot;/Library/Application Support/Titanium/mobilesdk/osx/1.7.0/titanium.py&quot; Linux alias titanium=&quot;$HOME/Library/Application Support/Titanium/mobilesdk/osx/1.7.0/titanium.py&quot; Windows XP PATH=C:\Documents and Settings\All Users\Application Data\Titanium\mobilesdk\win32\1.7.0 Windows Vista/7 PATH=C:\ProgramData\Titanium\mobilesdk\win32\1.7.0
Xcode project generated assets/  Classes/ ComWhymcaSmsdialogModule.h ComWhymcaSmsdialogModule.m ComWhymcaSmsdialogModuleAssets.h ComWhymcaSmsdialogModuleAssets.m example/ app.js   build.py   ComWhymcaSmsdialog_Prefix.pch  manifest  module.xcconfig  smsdialog.xcodeproj  titanium.xcconfig Asset files to be distributed with the module Implementation files Sample program for testing module invocations Script for building and packaging the module Metadata for managing the module in Titanium Include/linking directives used at integration-time Include/linking directives used at build-time To be filled with our code
3. Implementation The generated project already contains the class that implements the module: ComWhymcaSmsdialogModule The class name is a CamelCase transposition of the module id chosen when creating the project In JS it will be instantiated as var module = require(‘com.whymca.smsdialog’);
Implementing the proxy The SMSDialog object we defined, must be implemented as a proxy The name of the class must follow a convention similar to that used for the module name, in the form: < moduleID >< proxyName >Proxy i.e. ComWhymcaSmsdialog SMSDialog Proxy
SMSDialogProxy class Must be a subclass of the  TiProxy  class It should expose properties and methods that we want to make available to JavaScript code
Object creation and initialization var  smsDialog = module.createSMSDialog(); smsDialog.recipients = [ ’+391234567' ]; smsDialog.messageBody =  'Test message' ; //or var  smsDialog = module.createSMSDialog({ recipients: [ ’+391234567’ ], messageBody:  'Test message’ });
Creation Object creation is completely managed by the framework The JS construct module.create< ProxyName >() is mapped on code that instantiate an object of the correct class thanks to the naming convention used
Initialization The object can be initialized either passing a dictionary of property values to the factory method, either setting single property values in a second moment through dot notation In either case, if the proxy doesn’t explicitly provide getter/setter methods for those properties, they are automatically inserted in the  dynprops  dictionary of the proxy object
Initialization It’s always possible to retrieve property values present in the  dynprops  dictionary with the message  [self valueForUndefinedKey: @&quot;messageBody&quot; ]
Conversion utilities The framework provides the TiUtils class, which contains methods for simplifying the conversion of values coming form JS code: NSString * messageBody = [TiUtils stringValue:[self  valueForUndefinedKey: @&quot;messageBody&quot; ]]; UIColor * barColor = [[TiUtils colorValue:[self  valueForUndefinedKey: @&quot;barColor&quot; ]] _color]; BOOL animated = [TiUtils boolValue: @&quot;animated&quot;  properties:args def:YES];
Methods They are exposed to JavaScript by simply declaring them in the  @interface  section of the proxy class They must be declared in one of the following forms: -(id)methodName:(id)args -(void)methodName:(id)args
Example @interface ComWhymcaSmsdialogSMSDialogProxy: TiProxy <MFMessageComposeViewControllerDelegate>  - (id)isSupported:(id)args; - (void)open:(id)args; @end
Method arguments The list of arguments passed in JavaScript to a method is passed as a  NSArray  object in the  args  parameter The framework provides some C macros for the cases where a single argument is expected: ENSURE_SINGLE_ITEM(args,type) ENSURE_SINGLE_ARG_OR_NIL(args, type)
Passing JavaScript dictionary Objects JS: smsDialog.open({animated: true}); OBJ-C: - (void)open:(id)args { ENSURE_SINGLE_ARG_OR_NIL(args, NSDictionary); //args ora è un NSDictionary BOOL animated = [TiUtils boolValue: @&quot;animated&quot;  properties:args def:YES]; //[…]
Return values The types  NSString  NSDictionary  NSArray  NSNumber  NSDate  NSNull don’t need to be converted Numeric types must be wrapped in a  NSNumber  object It’s possible to return proxy objects (though they must be autoreleased if allocated by our method) return [[[TiColor alloc] initWithColor:color  name: @&quot;#fff&quot; ] autorelease];
Executing a method in the UI thread There are cases where a method should be executed in the UI thread (e.g. when interacting with user interface objects) In such cases we can use the macro ENSURE_UI_THREAD(method,args) for forcing the execution of the method on the UI thread
Events The simplest way a proxy has to interact with JS code is through events In JS we register an event-listener function on a specific event managed by the proxy Example JS: smsDialog.addEventListener( 'complete' ,  function (e){ Ti.API.info( 'Result: '  + e.resultMessage); });
Events OBJ-C: -(void)_listenerAdded:(NSString*)type count:(int)count  { //type = @&quot;complete&quot;   } -(void)_listenerRemoved:(NSString*)type count:(int)count { //type = @&quot;complete&quot;  }
Events OBJ-C: NSDictionary *event = [NSDictionary  dictionaryWithObjectsAndKeys:resultMessage,  @&quot;resultMessage&quot; ,  nil]; [self fireEvent: @&quot;complete&quot;  withObject:event];
4. Build We can build the project directly from Xcode Useful for checking out warning & syntax error messages
⌘ B
4. Build Using the script # build.py   from the module project root directory It performs a complete build and it packages the module library + assets + metadata in a zip file
Package Name in the form com.whymca.smsdialog-iphone-0.1.zip For being used it must be decompressed in the directory /Library/Application\ Support/Titanium/
Simple testing By executing the script # titanium run in the project directory This will create a temporary project based on the  app.js  file from the  example  directory Not the best way for testing the module
Using the module in a Ti Mobile Project <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?> <ti:app xmlns:ti=&quot;http://ti.appcelerator.org&quot;> <!–- SNIP… --> <modules> <module version=“0.1” platform=“iphone”> com.whymca.smsdialog </module> </modules> </ti:app> tiapp.xml
Testing/Debugging Create a new Ti Mobile project with test code and a reference to the module Launch the app at least one time from Ti Studio/Developer Open the Xcode project from the  build/iphone  directory found in the app project directory Issue  Build&Debug  from there Set breakpoints in the module code, test, etc.
 
Thank you! Any questions? You can find all the code used for this presentation on  https://github.com/omorandi/whymca-conf-2011

Extending Appcelerator Titanium Mobile through Native Modules

  • 1.
    Extending Titanium Mobilethrough Native Modules Olivier Morandi
  • 2.
    # whoami OlivierMorandi Freelance mobile developer & software engineer [email_address] @olivier_morandi https://github.com/omorandi
  • 3.
    Titanium Mobile Aset of tools for developing cross-platform mobile applications in JavaScript iOS (iPhone/iPod/iPad) Android Blackberry (through a commercial subscription) http://www.appcelerator.com https://github.com/appcelerator/titanium_mobile
  • 4.
    Anatomy of aproject Project directory build/ android/ iphone/ Resources/ app.js manifest tiapp.xml Project files Resource files: JS code, images, sounds, Sqlite DBs, etc. Build folders, per platform
  • 5.
    manifest #appname: whymca#publisher: olivier #url: http://www.whymca.org #image: appicon.png #appid: com.whymca.test #desc: undefined #type: mobile #guid: 746e9cb4-49f6-4afe-af0b-5de9f0116f65
  • 6.
    tiapp.xml <?xml version=&quot;1.0&quot;encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?> <ti:app xmlns:ti=&quot;http://ti.appcelerator.org&quot;> <deployment-targets> <target device=&quot;iphone&quot;>true</target> <target device=&quot;ipad&quot;>false</target> <target device=&quot;android&quot;>true</target> </deployment-targets> <id>com.whymca.test</id> <name>whymca</name> <version>1.0</version> <publisher>olivier</publisher> <url>http://www.whymca.org</url> <description>not specified</description> <copyright>2011 by olivier</copyright> <icon>appicon.png</icon> <persistent-wifi>false</persistent-wifi> <prerendered-icon>false</prerendered-icon> <statusbar-style>default</statusbar-style> <statusbar-hidden>false</statusbar-hidden> <fullscreen>false</fullscreen> <navbar-hidden>false</navbar-hidden> <analytics>false</analytics> <guid>746e9cb4-49f6-4afe-af0b-5de9f0116f65</guid> <iphone> <orientations device=&quot;iphone&quot;> <orientation>Ti.UI.PORTRAIT</orientation> </orientations> <orientations device=&quot;ipad&quot;> <orientation>Ti.UI.PORTRAIT</orientation> <orientation>Ti.UI.UPSIDE_PORTRAIT</orientation> <orientation>Ti.UI.LANDSCAPE_LEFT</orientation> <orientation>Ti.UI.LANDSCAPE_RIGHT</orientation> </orientations> </iphone> <android xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;> </android> <modules> </modules> </ti:app>
  • 7.
    app.js (1) varwin = Titanium.UI.createWindow({ title: 'Hello' , backgroundColor: '#fff' }); var label1 = Titanium.UI.createLabel({ color: '#333' , text: ’Hello World!' , textAlign: 'center' , font: {fontSize: 30, fontWeight: 'bold' } }); win. add (label1);
  • 8.
    app.js (2) varbt = Titanium.UI.createButton({ title: 'Click me' , width: 100, height: 40, bottom: 40 }) bt.addEventListener( 'click' , function (e) { label1.text = 'WHYMCA ROCKS!' ; }); win. add (bt); win. open ();
  • 9.
    UI widgets createdin JS are mapped on the native components of the target platform
  • 10.
    App distribution Theproduct ready for distribution is actually a native app JS Code Partially compiled and optimized Packed in binary format into the bundle Resources Copied into the bundle
  • 11.
    Development toolchain TiDeveloper (toolchain GUI) Ti Studio (IDE) Ti SDK toolchain (Python scripts) Mac OSX Mac OSX Windows Linux Xcode/iOS SDK Android SDK
  • 12.
    Application Stack JavaScriptApplication Code Titanium JavaScript API Android Modules iOS Modules Android SDK iOS SDK Titanium Framework JS Interpreter Runtime JS Interpreter Runtime
  • 13.
    Ti JavaScript APIhttp://developer.appcelerator.com/apidoc/mobile
  • 14.
    Extending the API:why? Accessing specific OS features Leveraging existing native libraries Optimizing critical portions of the app Extending/ameliorating portions of the Titanium Mobile framework
  • 15.
    Extending the API:how? Creating a fork of Titanium Mobile’s source code on github Unflexible approach You put your hands in the heart of the framework Maintaining a separate branch can be tedious and costly There are situations where this is the cheaper approach E.g. when needing to extend the functionality of core modules of the framework (networking, maps, ecc.)
  • 16.
    Extending the API:how? Creating one or more native modules throught the Titanium Module SDK Great flexibility Easy to distribute as Open Source Binary packages Appcelerator Ti+Plus Marketplace (?)
  • 17.
    Moduli nativi –some examples Android barcode scanner (Zxing wrapper) https://github.com/mwaylabs/titanium-barcode iOS ZipFile (create/decompress zip files) https://github.com/TermiT/ZipFile iOS TiStoreKit (in app purchase) https://github.com/masuidrive/TiStoreKit iOS TiSMSDialog (in app sms sending) https://github.com/omorandi/TiSMSDialog Appcelerator Titanium modules (sample modules) https://github.com/appcelerator/titanium_modules
  • 18.
    Titanium JS Interfacevar bt = Titanium.UI.createButton({ title: 'Click me' , width: 100, height: 40, bottom: 40 }); bt.addEventListener( 'click' , function (e) { label1.text = 'WHYMCA ROCKS!' ; });
  • 19.
    Titanium JS InterfaceModule Titanium.UI Object Titanium.UI.Button Object Factory Titanium.UI.createButton() Property getters/setters - methods Button.title Button.width Button.animate() Ecc. Event handling Button.addEventListener()
  • 20.
    Module Architecture Titanium.UITitanium.UI.Button Titanium.UI.Button.width Module Proxy Internal State setters/getters Methods Events Module Class Namespace Object Object property/method Proxy Class Implementation Titanium abstraction JavaScript Factory Internal State setters/getters Methods Events
  • 21.
    The path tomodule development Define the functionality you need to be exposed and how they’ll be invoked from JavaScript code  define the API of the module Create a project with the tools of the Module SDK Implement the API Build-Test-Debug
  • 22.
    Case Study –iOS SMS module The Titanium API provides email sending functionality through the Ti.UI.EmailDialog component, but nothing for sending SMS messages On iOS this feature is available since version 4.0 of the OS through the MFMessageComposeViewController class
  • 23.
  • 24.
    Case Study –iOS SMS module Implement a native module capable of exposing the features of the MFMessageComposeViewController class through a JavaScript API: Check the availability of the component (not present in iOS versions < 4.0) Programmatically set recipients and message body Set UI properties (e.g. navbar color) Notify the caller about the result of the send operation
  • 25.
    Resources Module SDKDocs Android http://wiki.appcelerator.org/display/guides/Module+Developer+Guide+for+Android iOS http://wiki.appcelerator.org/display/guides/Module+Developer+Guide+for+iOS Titanium Mobile source code https://github.com/appcelerator/titanium_mobile Code of other modules released as open source
  • 26.
    1. Defining theAPI Object SMSDialog Properties recipients messageBody barColor Methods isSupported() open()
  • 27.
    Example code var smsDialog = module.createSMSDialog(); if (smsDialog.isSupported()) { smsDialog.recipients = [ ’+14151234567' ]; smsDialog.messageBody = 'Test message from me' ; smsDialog.barColor = ’red' ; smsDialog.addEventListener( 'complete' , function (e){ Ti.API.info( 'Result: ' + e.resultMessage); }); smsDialog.open({animated: true}); }
  • 28.
  • 29.
    2. Creating theproject # titanium create --platform= iphone --type= module --dir= ~/ --name= SMSDialog --id= com.whymca.smsdialog
  • 30.
    titanium (alias) MacOS X alias titanium=&quot;/Library/Application Support/Titanium/mobilesdk/osx/1.7.0/titanium.py&quot; Linux alias titanium=&quot;$HOME/Library/Application Support/Titanium/mobilesdk/osx/1.7.0/titanium.py&quot; Windows XP PATH=C:\Documents and Settings\All Users\Application Data\Titanium\mobilesdk\win32\1.7.0 Windows Vista/7 PATH=C:\ProgramData\Titanium\mobilesdk\win32\1.7.0
  • 31.
    Xcode project generatedassets/ Classes/ ComWhymcaSmsdialogModule.h ComWhymcaSmsdialogModule.m ComWhymcaSmsdialogModuleAssets.h ComWhymcaSmsdialogModuleAssets.m example/ app.js build.py ComWhymcaSmsdialog_Prefix.pch manifest module.xcconfig smsdialog.xcodeproj titanium.xcconfig Asset files to be distributed with the module Implementation files Sample program for testing module invocations Script for building and packaging the module Metadata for managing the module in Titanium Include/linking directives used at integration-time Include/linking directives used at build-time To be filled with our code
  • 32.
    3. Implementation Thegenerated project already contains the class that implements the module: ComWhymcaSmsdialogModule The class name is a CamelCase transposition of the module id chosen when creating the project In JS it will be instantiated as var module = require(‘com.whymca.smsdialog’);
  • 33.
    Implementing the proxyThe SMSDialog object we defined, must be implemented as a proxy The name of the class must follow a convention similar to that used for the module name, in the form: < moduleID >< proxyName >Proxy i.e. ComWhymcaSmsdialog SMSDialog Proxy
  • 34.
    SMSDialogProxy class Mustbe a subclass of the TiProxy class It should expose properties and methods that we want to make available to JavaScript code
  • 35.
    Object creation andinitialization var smsDialog = module.createSMSDialog(); smsDialog.recipients = [ ’+391234567' ]; smsDialog.messageBody = 'Test message' ; //or var smsDialog = module.createSMSDialog({ recipients: [ ’+391234567’ ], messageBody: 'Test message’ });
  • 36.
    Creation Object creationis completely managed by the framework The JS construct module.create< ProxyName >() is mapped on code that instantiate an object of the correct class thanks to the naming convention used
  • 37.
    Initialization The objectcan be initialized either passing a dictionary of property values to the factory method, either setting single property values in a second moment through dot notation In either case, if the proxy doesn’t explicitly provide getter/setter methods for those properties, they are automatically inserted in the dynprops dictionary of the proxy object
  • 38.
    Initialization It’s alwayspossible to retrieve property values present in the dynprops dictionary with the message [self valueForUndefinedKey: @&quot;messageBody&quot; ]
  • 39.
    Conversion utilities Theframework provides the TiUtils class, which contains methods for simplifying the conversion of values coming form JS code: NSString * messageBody = [TiUtils stringValue:[self valueForUndefinedKey: @&quot;messageBody&quot; ]]; UIColor * barColor = [[TiUtils colorValue:[self valueForUndefinedKey: @&quot;barColor&quot; ]] _color]; BOOL animated = [TiUtils boolValue: @&quot;animated&quot; properties:args def:YES];
  • 40.
    Methods They areexposed to JavaScript by simply declaring them in the @interface section of the proxy class They must be declared in one of the following forms: -(id)methodName:(id)args -(void)methodName:(id)args
  • 41.
    Example @interface ComWhymcaSmsdialogSMSDialogProxy:TiProxy <MFMessageComposeViewControllerDelegate> - (id)isSupported:(id)args; - (void)open:(id)args; @end
  • 42.
    Method arguments Thelist of arguments passed in JavaScript to a method is passed as a NSArray object in the args parameter The framework provides some C macros for the cases where a single argument is expected: ENSURE_SINGLE_ITEM(args,type) ENSURE_SINGLE_ARG_OR_NIL(args, type)
  • 43.
    Passing JavaScript dictionaryObjects JS: smsDialog.open({animated: true}); OBJ-C: - (void)open:(id)args { ENSURE_SINGLE_ARG_OR_NIL(args, NSDictionary); //args ora è un NSDictionary BOOL animated = [TiUtils boolValue: @&quot;animated&quot; properties:args def:YES]; //[…]
  • 44.
    Return values Thetypes NSString NSDictionary NSArray NSNumber NSDate NSNull don’t need to be converted Numeric types must be wrapped in a NSNumber object It’s possible to return proxy objects (though they must be autoreleased if allocated by our method) return [[[TiColor alloc] initWithColor:color name: @&quot;#fff&quot; ] autorelease];
  • 45.
    Executing a methodin the UI thread There are cases where a method should be executed in the UI thread (e.g. when interacting with user interface objects) In such cases we can use the macro ENSURE_UI_THREAD(method,args) for forcing the execution of the method on the UI thread
  • 46.
    Events The simplestway a proxy has to interact with JS code is through events In JS we register an event-listener function on a specific event managed by the proxy Example JS: smsDialog.addEventListener( 'complete' , function (e){ Ti.API.info( 'Result: ' + e.resultMessage); });
  • 47.
    Events OBJ-C: -(void)_listenerAdded:(NSString*)typecount:(int)count { //type = @&quot;complete&quot; } -(void)_listenerRemoved:(NSString*)type count:(int)count { //type = @&quot;complete&quot; }
  • 48.
    Events OBJ-C: NSDictionary*event = [NSDictionary dictionaryWithObjectsAndKeys:resultMessage, @&quot;resultMessage&quot; , nil]; [self fireEvent: @&quot;complete&quot; withObject:event];
  • 49.
    4. Build Wecan build the project directly from Xcode Useful for checking out warning & syntax error messages
  • 50.
  • 51.
    4. Build Usingthe script # build.py from the module project root directory It performs a complete build and it packages the module library + assets + metadata in a zip file
  • 52.
    Package Name inthe form com.whymca.smsdialog-iphone-0.1.zip For being used it must be decompressed in the directory /Library/Application\ Support/Titanium/
  • 53.
    Simple testing Byexecuting the script # titanium run in the project directory This will create a temporary project based on the app.js file from the example directory Not the best way for testing the module
  • 54.
    Using the modulein a Ti Mobile Project <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?> <ti:app xmlns:ti=&quot;http://ti.appcelerator.org&quot;> <!–- SNIP… --> <modules> <module version=“0.1” platform=“iphone”> com.whymca.smsdialog </module> </modules> </ti:app> tiapp.xml
  • 55.
    Testing/Debugging Create anew Ti Mobile project with test code and a reference to the module Launch the app at least one time from Ti Studio/Developer Open the Xcode project from the build/iphone directory found in the app project directory Issue Build&Debug from there Set breakpoints in the module code, test, etc.
  • 56.
  • 57.
    Thank you! Anyquestions? You can find all the code used for this presentation on https://github.com/omorandi/whymca-conf-2011