Appcelerator Developer Blog

What is a Titanium “proxy” object?

First a PSA: Older versions of Apple’s Application Loader have been reported to cause problems on app submission related to icon sizes. Updating to the latest app loader resolves the issue. Related Q&A post here.

The following is the first in a series of Friday blog posts covering advanced topics and Titanium development best practices.

If you’ve followed the developer blog and read through our documentation out on the wiki, you’ve probably come across the phrase “proxy object” on a few occasions.  Basically, a proxy is a special JavaScript object which is a stand-in for a corresponding object in native code (on iOS or Android – this magic layer is not needed on mobile web).  

//"button" is a proxy object
var button = Ti.UI.createButton({
	title:'push me!',
        height:50,
        width:200
});

For a more detailed explanation of what a proxy is and how it works, check out our module development guide, which goes through the process of creating your own native modules for iOS and Android.

Any time you are interacting with a function or property in the Ti.* JavaScript namespace, or dealing with an object you got back from a function in this namespace, that object is a proxy of some type.  In order to facilitate communication “over the bridge” from the JavaScript context to native code, these proxy objects have been instrumented with special behavior which allows native code (Java, C, or Objective-C) to intercept assignments and function calls to these objects.  This model of interaction is what allows developers to essentially write native code in JavaScript, and makes Titanium distinct from many other other cross-platform tools.

Proxies Are Special

As a user of the platform, though, it is helpful to understand a few things about these objects.  At least in the 1.x and probably for most of the 2.x timeframe, proxy objects won’t always play by the rules of JavaScript. Let’s take a look at some areas where the rules of JavaScript get bent or broken.  

Nested Objects

In a normal JavaScript object, you can set nested properties on objects (so long as those properties/objects exist), as in “meaning.of.life = 42;”. With proxies, this cannot be done. One notable place where you’ll run into this is with the “font” property of Labels. In the example below, the “l” object is a proxy, which should have a nested property font, and then fontSize associated with it. Trying to set the nested property fontSize directly does not work, but setting the entire font object to a new value does:

var w = Ti.UI.createWindow({
	backgroundColor:'white'
});
 
var l = Ti.UI.createLabel({
	text:'here is a label',
	font: {
		fontFamily:'Trebuchet MS'
	}
});
w.add(l);
 
//doesn't work
l.font.fontSize = 24;
 
//this does work
l.font = {
	fontFamily:'Trebuchet MS',
	fontSize: 24
};
 
w.open();

Overriding Properties

Another behavior of proxy objects is that the functions defined as the public interface of a proxy object (functions and properties Titanium expects to use) cannot be overridden as they could be with typical JavaScript objects. The following is legal JavaScript code:

var window = Ti.UI.createWindow({
	backgroundColor:'red'
});
 
window.open = function() {
	alert('overriding open!');
};
 
window.open();

But when run, you’ll notice that since “open” is a function that is part of the proxy’s public interface, the “built in” open functionality remains, even though we think we’ve overridden it:

Getters and Setters

Certain function names also have magic associated with them. Any function prefixed with “get” or “set” will be delegated to native code, so any custom getters or setters you’d like to set up on a proxy will be ignored:

var window = Ti.UI.createWindow({
	backgroundColor:'red'
});
 
window.getSomething = function() {
	alert('getter function');
};
 
window.setSomething = function(something) {
	alert('trying to set '+something);
};
 
window.open();
 
//will be ignored
window.getSomething();
window.setSomething('foo');

.apply and .call

For instance, normally you can call any Function in JavaScript using .apply or .call, since functions are first class objects.  With Titanium proxy objects, because of their special plumbing, you’re not able to do this out of the box.  The following is code that should be rational:

var window = Ti.UI.createWindow.call(this,{
	backgroundColor:'red'
});
window.open();

But produces a red screen of death on iOS:

Wrapping Proxies

Occasionally this behavior becomes annoying, because we expect to be able to use all the JavaScript tricks up our sleeves on the objects which are part of or produced by the Ti.* namespace. When dealing with a proxy directly presents a problem, a common approach is to wrap a proxy object in a regular JavaScript object with no link to an object in “native land”. It can be as simple as the following example, which could be placed at the root of a Titanium project directory:

Resources/WrappedWindow.js

//Proxy wrapper
function WrappedWindow(args) {
	this.proxy = Ti.UI.createWindow(args);
}
 
WrappedWindow.prototype.open = function(args) {
	this.proxy.open(args);
};
 
WrappedWindow.prototype.setBackgroundColor = function(color) {
	//this works because WrappedWindow is just a plain ol' JS object!
	this.proxy.animate({
		backgroundColor:color,
		duration:4000
	});
};
 
module.exports = WrappedWindow;



Resources/app.js

var WrappedWindow = require('WrappedWindow');
 
var w = new WrappedWindow({
	backgroundColor:'white'
});
 
w.open();
w.setBackgroundColor('red');

Using this technique, you can avoid the special behavior of proxies when working with them directly is a pain in your neck.

Summary

A proxy object is the bridge that empowers you to write a native app in JavaScript. However, they do have some special rules applied to them. The big ones to watch out for are:

  • Can’t set properties of nested objects
  • Unable to override properties in the proxy’s public API
  • Functions prefixed with “get” and “set” are intercepted
  • .call and .apply don’t work on proxy objects

When this behavior presents a problem, it becomes useful to wrap a proxy object in a plain JavaScript object, which will “play by the rules” of JavaScript. Next week, we’ll be looking at a more complex way to use this object wrapper technique to build custom components with CommonJS modules. See you next time!


Older versions of Apple’s App Loader Broken

There have been a few reports out there of older versions of Apple’s app loader causing problems during app submissions, erroneously claiming that the app icons are the wrong size. Updating to the latest version of the app loader from Apple should resolve this issue. The relevant Q&A post can be found here. Thanks and let us know if you have any issues with this.


Titanium Mobile 1.8.1 is available now

We’re excited to announce that Titanium Mobile SDK 1.8.1 and Titanium Studio 1.0.8 are now available. We released Titanium Mobile 1.8 in late December with many new features and enhancements including V8 runtime support for Android and the overall response has been very positive.

We’ve decided to release monthly service packs to address high priority issues so that our community has access to well tested releases instead of relying on CI builds. Titanium Mobile SDK 1.8.1 is our first service pack release; it builds on the strengths of Release 1.8.0.1, and addresses over 200 issues.

Enhancements in 1.8.1 include:

  • iOS & Android – Added Blob support for Ti.Map.Annotation.image
  • iOS – Support for repeating backgrounds on a view
  • iOS – Support for getting current latitude and longitude delta from a MapView
  • iOS – Ability to disable animation when setting the contentOffset on a ScrollView
  • Documentation – Added a new Titanium Debugging and Profiling chapter to the guide
  • Documentation – Improved API documentation with new code examples

Read the Release Notes for additional details on all improvements available in this release.

Download and Installation

Updating Titanium Studio

You should be automatically prompted to update your Titanium Studio software. If you do not see the prompt, you can select “Check for Updates” from the “Help” menu from within Titanium Studio.

Updating the Mobile SDK

Similarly, you should be prompted to automatically upgrade your Titanium Mobile SDK from within Titanium Studio. If you do not see the prompt below, you can manually check for updates by selecting “Check for Titanium SDK Updates” from the “Help” menu within Titanium Studio.

For More Information

For more information, you may view the related API Documentation: Titanium Mobile SDK 1.8.1 API docs.


Join Appcelerator at Mobile World Congress

Are you going to MWC?  Appcelerator will be on hand for MWC, and would be honored by your presence at a developer meetup at 7pm on Tuesday, February 28th.  Appcelerator CEO Jeff Haynie and COO Sandeep Johri will be on hand to meet developers, and members of the European Titanium developer community will be presenting their amazing achievements on top of the Titanium platform.

Further speaker and event details are forthcoming, but you can register for the event today at the link below.  We hope to see you there!

http://appc-mwc.eventbrite.com/


The Future of Titanium Desktop

Titanium Desktop is a remarkable open source project.  The ability to deploy a Webkit-based desktop application across all three major desktop operating systems, with privileged access to native APIs, has empowered web developers to escape the browser and deliver rich, “always on” desktop apps.  Today, we’re announcing the next phase of the Desktop project, as we call for leaders and contributors in the Desktop development community to take the reins and decide Titanium Desktop’s future.

With the increasing divergence in architecture between Titanium Desktop and Titanium Mobile, we feel the time is now right to spin off the Desktop project into a separate, community-driven project.  If you are interested in helping chart the course of the Desktop project in the future, please join us on this mailing list as we take the first steps toward establishing an independent governance and technical leadership structure for the Desktop project.

Our decision to split Desktop off into its own project is not a reflection on the technology its self, but rather on our goals and focus as a company.  Appcelerator is committed to delivering the best mobile application development platform in the world, and we feel that we need to focus in 100% on that goal.

The new Desktop project, which will undergo a name change from Titanium Desktop, will be governed and developed by the Desktop community, with material, administrative and logistical support from Appcelerator, but limited development resources. From the Appcelerator side, I will be acting as the liaison for this community to Appcelerator, and facilitate any action or assistance that needs to be rendered from our end. To participate actively in the transition, please join the Google Group here:

http://groups.google.com/group/titanium-desktop-transition

Below is a rough roadmap of what changes we intend to make, and when we would like to make them.

  • January 2012:
    • Call for participation in the Desktop community
      • Interested parties will sign up for an ad hoc group of potential developers and contributors (titanium-desktop-transition Google group)
      • Open call for alternative names for Titanium Desktop, as the Titanium brand will remain only for what is today the titanium_mobile codebase
      • Governance structures will be put in place for this project, modeled loosely after other major community-driven software projects, such as jQuery.
      • Nominations for a project board of directors will take place.  Board of directors will form the primary governance structure for the reformed Titanium Desktop project
      • Board will govern the project by parliamentary procedure (Motions: http://en.wikipedia.org/wiki/Parliamentary_motion) – majority rules on project decisions.
    • Project wiki and web site created
  • February 2012
    • Board will appoint a technical lead for the desktop project.  Appcelerator will work to provide GitHub repository administration and any administrative support needed
      • Development support will be provided as best we can to help facilitate the transition to a new technical lead, and to get the project off to a rolling start
    • Technical lead will provide a roadmap for the next release version of the Desktop SDK.  Can use Appcelerator JIRA or a bug reporting suite of their choosing
    • Technical lead will submit a list of JIRA or work items for approval as the backlog for the 1.0 release of the re-branded Desktop
  • March 2012
    • Backlog will be worked through by interested peers in the Desktop community
    • When the backlog has been depleted, the technical lead will create a release of the desktop software.
    • Technical lead and board of directors will begin work on the next phase of the roadmap.
    • NOTE: Desktop project support dropped from Titanium Studio by end of month
    • NOTE: Appcelerator-managed desktop packaging servers may be taken down at this time – we may leave them up slightly longer, but reserve the right to shut down the service at this time
    • API and reference documentation for Titanium Desktop 1.1 moved to new project web properties
  • September-December 2012
    • Assuming the completion of a release or releases by the newly formed Desktop team, Appcelerator will initiate an application for contributing the Desktop codebase to both the Apache Software Foundation and the Free Software Conservancy, with whom we’ve already been in contact.
    • If accepted to either, financial sponsorship and the transition of authority will pass from Appcelerator to the new sponsor.

 

Once again, we encourage all members of the Titanium Desktop community to be a part of this project.  We think there is a bright future for the Desktop project, and look forward to supporting its community in the next phase of the project’s development.

Page 32 of 91« First...1020...3031323334...405060...Last »