The Perfect Storm – AIR iOS simulator/TLF issues

Was making changes to an app built with Flash for iOS, when I discovered that incompatibilities between the new XCode and Flash means that no longer(at the time of writing) is it possible to test or debug on the iOS simulator nor on the device. (see adobe forum posts) Usually you can pick up on problems just outputting to a SWF, but unfortunately my SWF looked fine and the IPA just sat there with a black screen, not even showing an image that was on the stage.

So – diagnosing the problem without seeing the errors was a challenge! A very weird black screen problem + not being able to see errors = the perfect storm! But in investigating the possibility of a connection with TLF Text Fields(as it was exporting ok in CC, but the design had a lot of TLF that I didn’t want to reposition) I managed to work it out – As Curtis Morley discusses in his blog, since AIR 3.5:

In AIR for iOS, TLF Text is required to be merged with your code(rather than using a Runtime Shared Library)

Worth remembering!

Tagged with: ,
Posted in AIR

Punctuation in RTL text in Objective C

In the subtitles project I’m working on, I had the need to display Hebrew and Arabic, both RTL (right to left) languages. Having not worked with RTL text before, I wasn’t aware of the headache they can be, especially when combined with LTR text. A problem I discovered in Objective C, was that when displaying RTL text that finished with punctuation(which is considered LTF text), instead of showing at the left of the textfield(left is the end of RTL text!), it was incorrectly showing at the right. You can see how this can happen by copying the contents of the string below, and pasting it into the URL box of this browser window.

After some research into Bidirectional text, I discovered that there exists unicode characters that indicate properties of the text that follows. Through experimentation I found one of these characters forced the punctuation to display in the correct place in the textfield. So, if you know that the string contains RTL text, prefix the string with the “Right-to-Left Isolate” character(unicode character 2067).

self.label.text = [@"\u2067" stringByAppendingString: @",הם הכריחו אותה לשתות ויסקי"];
Tagged with: , ,
Posted in Objective C

Optional parameters in methods in Objective C

Methods in Objective C are actually called messages but they’re often referred to as methods, a more commonly used terminology.

Optional parameters are treated in an interesting way in Objective C. Basically there are no optional parameters! In fact the parameters help to define the method.

To illustrate this, rather than the following method being the ‘printFirstName’ method, it is actually best envisaged as the ‘printFirstName:surname:’ method.

-void printFirstName:(NSString *)firstName surname:(NSString *)surname;

To explain: ‘surname:(NSString *)surname’ – the first ‘surname’ is the parameter name as seen external to the method, the second ‘surname’ is the variable name for the parameter within the method.

In Actionscript for example you can have a method with an optional parameter:

function printThings(firstThing:String,secondThingOptional:String=’’):void

So how to do something similar in Objective C? You can create two methods, one without the optional parameter, and one with the optional parameter. The method without the optional parameter can then call the method with the optional parameter specifying the default. So we would could something like the following:

-void printFirstName:(NSString *)firstName surname:(NSString *)surname; {
	//...
}
-void printFirstname:(NSString *)firstName; {
	[self printFirstName:firstName surname:@""];
}

The two methods are called ‘printFirstname:’ and ‘printFirstname:surname:’. At first glance, the second method seems to be called ‘printFirstName’ which doesn’t make sense as it also prints surname. However, ‘surname:’ is actually part of the name of the method. (it also externally names the second parameter)

For more on optional parameters, I’ve taken a look at them in Swift here.

Tagged with: ,
Posted in Objective C

Default String representation of an NSObject

In Actionscript, if you subclass Object, and you want a default string representation of your subclass, you just implement the method ‘toString’. For example the following:

package {
	public class Thing { 
		public var name:String;
		public function toString() : String {
			return (“Thing: “+this.name);
		}
	}
}
...
var thing:Thing = new Thing();
thing.name = “thing”
trace(thing);  //trace: Thing: thing

In Objective C, it’s very similar, however instead of ‘toString’ you use ‘description’.

#import <Foundation/Foundation.h>

@interface Thing : NSObject
@property (strong,nonatomic) NSString *name;
@end

@implementation Thing
- (NSString *)description {
    return [NSString stringWithFormat: @"Thing: %@", self.name];
}
@end

...

Thing *thing = [[Thing alloc] init];
thing.name = @"thing"
NSLog(@"Thing: %@",thing);//log: Thing: thing

Tagged with: ,
Posted in Objective C

Getters and Setters in Objective C

Doing a lot of Objective C lately, thought it worthwhile to write a few key differences with Actionscript. To begin with today – getters and setters!

Properties in Objective C are automatically given setters and getters eg:

@property (strong,nonatomic) NSString *name;

is automatically given:

the getter:

-(NSString *)name
{
	return _name;
}

the setter:

-(void)setName:(NSString *)name
{
	_name = name;
}

You can replace these in your code. If you replace both, you need to add the line:

@synthesize name = _name;
Tagged with:
Posted in Objective C

the trick for registering a class for shared object

registerClassAlias is a great way for SharedObject to recognise the class type that you’re storing rather than just a random object. However – something that seems to be undocumented – I’ve discovered that the constructor of the class you’re registering either has to have NO parameters OR default values for all parameters.

So: for example, if you’re trying to store a class and its constructor looks like this:

function user(userName:String,userID:String):void {

it won’t work until you give the parameters defaults, for example:

function user(userName:String='',userID:String=''):void {
Tagged with: ,
Posted in Flash

Publishing Android app in the Air Developer Tool

I’ve been working on an Android app lately, built in ActionScript. There’s a problem within the Flash IDE when publishing an Android app, that the icons available haven’t yet been updated to include 96×96 and 144×144. There’s been talk of an update to resolve this issue for some time, but I’m not holding my breath, and there’s an alternative (shudder) command-line solution – the Air Developer Tool(ADT). If working in the command-line wasn’t a pain already, ADT is a bit of a finicky beast. So I’m writing here for future reference the steps I’ve taken to publish my Flash based app to an apk file(for testing on Android).

STEP 1: Open Terminal, add path of ADT to global path (use backslash to escape spaces)

export PATH=$PATH:/Applications/Adobe\ Flash\ CS6/air3-9_sdk_mac/bin

STEP 2: check all is good and we can access ADT:

adt -version

STEP 3: change directory to project home

cd /Users/user/Projects/source

STEP 4: run adt with all the appropriate parameters making sure all the parameters are in the correct order (i encountered errors until i moved ‘-target apk’ to before the certificate.

adt -package -target apk -storetype pkcs12 -keystore /Users/user/Development/certificates/androidCertificate.p12 -storepass password myapp.apk myapp-app.xml myapp.swf otherFiles

Tagged with: , , , ,
Posted in AIR, Flash

binding functions

I’ve been working on a Space Invaders style game with the request from the client that it be “developed in HTML5 and works in IE8”.(!!) A bit of a contradiction in terms. Google Chrome Frame seemed like a possible solution until they told me that no new software/plugins could be installed(and it’s goodbye to chrome frame anyway shortly).

I decided in the end to just set up two versions, one in JavaScript and the other in ActionScript. Was quite an interesting exercise, examining the similarities and differences between them. I may write more about general differences in a later post. But one difference is worth its own post:

bind(this)

For an event handler to retain its scope, you need to specify its scope, for example:

this.getStage().addEventListener('click', this.onMouseDown.bind(this));

But what this actually does is replicate the function bound to the instance. Even if the function is part of the object, it doesn’t retain its scope.

This took me a while to work out, but if you try to remove the event listener, neither of the following two lines work:

this.getStage().removeEventListener('click', this.onMouseDown);
this.getStage().removeEventListener('click', this.onMouseDown.bind(this));

Because neither of them actually refer to the original function created by the bind function, you need to actually create a new variable to begin with, containing the bound function, and then later when removing the event listener, refer to this variable:

this.onMouseDownBound = this.onMouseDown.bind(this);
this.getStage().addEventListener('click', this.onMouseDownBound);
...
this.getStage().removeEventListener('click', this.onMouseDownBound);
Tagged with: ,
Posted in JavaScript

State Manager

I was working recently on a MovieClip which had several different states, where the elements were in different positions, or in some states certain elements didn’t exist. I guess there are two common solutions to dealing with this – 1: animating the transitions between the states on the timeline OR 2: describing all the different states in code, and using Tweens such as greensocks to make the transitions.

There are problems with both ways:

Solution 1 is time consuming setting up animations on the timeline, especially if there are changes down the track. It also gets ridiculous if there are many states and the transitions don’t go back to a neutral state before animating to the next state.

Solution 2 is a purely code solution so once the design is set up, it’s then generally up to the developer to translate the designer’s work to something that can be fed into the tween classes Again this can be time-consuming, especially when there are changes.

So I was thinking the other day, wouldn’t it be cool if you(or preferably the designer!) could just prepare the different states in a movieclip on different frames with frame labels, and BAM, the states are set and merely by requesting that state, the elements perform the appropriate tween.

We could still use the designer’s work, but we wouldn’t need to translate the design to code. The tweens would all be automatic and changes would be easy to implement.

So here’s my idea, I’ve called the class StateManager. To use it your movieclip just needs to use it as a base class, and then to go to a different state(for example, ‘initState’), just call:

goState('state1');

The default tween time is 0.5 seconds, this is also an optional parameter you can pass:

goState('state2', 1);

For an example of how to use this class, click here.

At the moment the only properties that are tweened are x,y, alpha, scaleX and scaleY. If further properties seem to be necessary they could be included easily.

Here it is, feel free to comment, interested to know what people think.

package com.craiggrummitt.display
{
    import com.greensock.TweenLite;
    import com.greensock.plugins.AutoAlphaPlugin;
    import com.greensock.plugins.TweenPlugin;
    
    import flash.display.DisplayObject;
    import flash.display.FrameLabel;
    import flash.display.MovieClip;
    import flash.text.TextField;
    
    public class StateManager extends MovieClip
    {
        private var displayObjectInstances:Array;
        private var labelObjectStates:Array;
        public function StateManager()
        {
            super();
            TweenPlugin.activate([AutoAlphaPlugin]);
            init();
            removeAll();
            goState(currentLabels[0].name,0);
        }
        private function init():void {
            displayObjectInstances=[];
            labelObjectStates=[];
            for (var i:int=0;i<currentLabels.length;i++) {
                var label:FrameLabel=currentLabels[i] as FrameLabel;
                initState(label.name);
            }
        }
        private function removeAll():void {
            do {
                this.removeChildAt(0);
            } while (this.numChildren>0);
        }
        public function goState(stateName:String,time:Number=0.5):void {
            for (var displayObjectInstance:String in displayObjectInstances) {
                var displayObject:DisplayObject=displayObjectInstances[displayObjectInstance];
                var state:Object=labelObjectStates[stateName][displayObjectInstance];
                if (!this.getChildByName(displayObject.name)) this.addChild(displayObject);
                
                if (state) {
                    TweenLite.to(displayObject,time,{x:state.x,y:state.y,autoAlpha:state.alpha,scaleX:state.scaleX,scaleY:state.scaleY});
                } else {
                    TweenLite.to(displayObject,time,{autoAlpha:0});
                }
            }
        }
        private function initState(label:String):void {
            gotoAndStop(label);
            labelObjectStates[label]=[];
            for (var i:int=0;i<this.numChildren;i++) {
                var obj:DisplayObject=this.getChildAt(i);
                if (!displayObjectInstances[obj.name]) {
                    displayObjectInstances[obj.name]=obj;
                }
                labelObjectStates[label][obj.name]={x:obj.x,y:obj.y,alpha:obj.alpha,scaleX:obj.scaleX,scaleY:obj.scaleY};
            }    
        }
    }
}
Tagged with: ,
Posted in Flash

Custom components – order of parameters

A pain with parameters in custom components is that the order is set to alphabetical, and there’s nothing you can do about it. It’s a pain, because you might want better consistency to your parameters in different components, or to put the higher priority parameters first…

I’d already resigned myself to this fact when I happened upon a comment in a six year old blog post with a sneaky solution.

Add the unicode character \u200b to a parameter and it will come before the others. Add two of the same unicode characters and it will come before that one. And so on. It’s just like aaaa at the beginning of the phone book.
eg.

[Inspectable(name="\u200B\u200BItem no:")]
public var itemNo:int;
[Inspectable(name="\u200BXML tag:")]
public var xmlTag:String;
[Inspectable(name="Scale:")]
public var scale:Number;

will put the parameters in the order:
Item no:
XML tag:
Scale:

Tagged with:
Posted in Flash