Archive for the 'Extensibility' category

iPhone App Launch Sequence

May 22 2009 Published by keith under Brevity, Extensibility, Objective C, iPhone

I was going over the stuff I’m going to cover next week in my “From Flash to iPhone” workshop at Flash on Tap, and I started getting into how an iPhone app launches when you tap its icon. It might be a bit heavy to go into detail on it at the workshop, but I thought it was pretty interesting and writing about it might shed some light for developers moving past the newbie phase.

Coming from the Flash/Flex world – app start up is pretty simple. You specify a main class. When the SWF is launched, that class is instantiated, calling its constructor. Whatever is in the constructor of that main class is what happens.

But in your typical iPhone apps, you have C files, Objective-C classes, xibs, pchs, frameworks, and plists. Which is the chicken, which is the egg, and which comes first?

First of all, realized that Objective-C is an extension of C to add object oriented capabilities. If you’ve ever taken a C course, or cracked open a book on C, you’re going to see a file like this:

#include <stdlib.h>

int main(int argc, char *argv[]) {
            printf("Hello World");
            return 0;
}

When you run the program, it looks for a function called “main” and runs it. It passes in the number of command line arguments (int argc) and an array of strings that are the arguments. It executes whatever code is in that function and then exits, returning an int – usually 0 means it exited as usual, anything else means some kind of error.

Well, it turns out that Objective-C programs launch in exactly the same way. In fact, if you fire up XCode and create a Window Based Application named “Test”, you’ll see a file under “Other Sources” called “main.m”. It contains this:

#import <uikit/UIKit.h>

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

This is the first bit of code that gets executed when you launch an app. For the most part, you don’t want to mess with it, unless you really know what you are doing. So what does it do? Creates an autorelease memory pool and then calls a function called UIApplicationMain, passing in the command line arguments, and two other nil arguments. We’ll see what at least one of those is in a bit.

UIApplicationMain creates whatever UI you have created and starts the program loop. Which means it just loops and sits there waiting for events. Eventually at some point, the user quits the program. This ends the execution of the UIApplicationMain method, returning an int return value. The main function releases the memory pool it created and returns that return value to the system. That’s all.

So if UIApplicationMain is a standard function in UIKit, how does it know about your classes and interfaces and stuff? Well, one of the first things it does is to read your Info.plist file, which looks something like this, if you view it as xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleDisplayName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundleExecutable</key>
	<string>${EXECUTABLE_NAME}</string>
	<key>CFBundleIconFile</key>
	<string>icon.png</string>
	<key>CFBundleIdentifier</key>
	<string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>${PRODUCT_NAME}</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>1.0</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSMainNibFile</key>
	<string>MainWindow</string>
</dict>
</plist>

You’ll notice the last key/value pair theire is NSMainNibFile, which is set to MainWindow. You can also set this value in the Target info window:

target_info

You see the “Main Nib File:” entry way down at the bottom. Setting the value in this window, simply rights it into the plist file.

And what do you know, we happen to have a .xib (nib) file called MainWindow.xib in our project! Coincidence? I think not. Let’s take a look at that. Double click on it to open it in Interface Builder. The window itself is uninteresting, but the Document window shows us all the stuff that’s defined in here:

xibcontents

So main starts UIApplicationMain, which looks at the Info.plist file, sees this nib is the main nib, and loads it in. For most of the items in there that are linked to classes, it will create an instance of that class, deserialize any properties, styles, etc. you might have set on it, and then hook up any outlets or actions you might have set on it. So what do we have here?

First we have an entry called “File’s Owner” This is linked to the UIApplication class. So an instance of UIApplication is created. Yay!As clarified in the comments, UIApplication is actually created by the call to UIApplicationMain. The entry here merely links to that instance that gets created. It exists here mainly so we can set its delegate, as we will see soon.

Then we have “First Responder”. This is a bit of a special case, i.e. I don’t fully understand it. ;) But my understanding is that this does not get instantiated per se, but is a fill in for another class that will be responding to events.

Next up we have “Test App Delegate” which is linked to the class TestAppDelegate. If you jump back into XCode, you’ll see that you do indeed have a class with that name. So this class is instantiated.

Finally, we have “Window”, which is of type UIWindow. So we get one of those.

So the result of this is we now have instances of UIApplication, TestAppDelegate, and UIWindow created. Now, if you click on the Window object and look at the Attributes tab in the Inspector, you’ll see there are various properties you can set on it, such as scale mode, alpha, background color, tag, opaque, hidden, etc. The size tab also has dimensional and layout properties that can be assigned. Any properties set here are then set on the newly created objects.

Finally, we go to the connections tab. This is where our outlets and actions are defined. If you look at UIApplication, you’ll see it has an outlet called delegate, which is set to Test App Delegate. This is the same as calling setDelegate on the UIApplication instance, and passing in the instance of TestAppDelegate. Also note that TestAppDelegate has an outlet called window which is set to the Window instance. We are not going to dive into UIApplication’s code, but if you look at TestAppDelegate.h, you’ll see it has a @property called window, which is indeed a UIWindow.

#import <uikit/UIKit.h>

@interface TestAppDelegate : NSObject <uiapplicationDelegate> {
    UIWindow *window;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

@end

So now our UIApplication instance has a reference called delegate which points to our instance of TestAppDelegate, and that has a referenced called window which points to the UIWindow instance. We are done with the nib.

Now, UIApplication starts its event loop. When certain events occur, it passes them over to its assigned delegate to handle. The first, and most important event it delegates is “applicationDidFinishLaunching”. This means that all this plist and nib loading and deserializing and whatever else it needs to do, is done. So it calls the applicationDidFinishLaunching on its delegate.

And, look at that, our TestAppDelegate class just happens to have a method with that very same name.

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Override point for customization after application launch
    [window makeKeyAndVisible];
}

All this does by default is take that window that was set and make it the key, visible window.

And that’s where it ends. If you want to do more, you would add code in that applicationDidFinishLaunching method to create views, view controllers, or whatever else.

Now, if you had created a View Based application, a lot of this would be the same, but you’d also have a TextViewController nib. This would be loaded by the MainWindow nib. This new nib would contain a reference to the TestViewController class, and a UIView linked to the view outlet on that view controller. So an instance of this view controller and a UIView would be created. In applicationDidFinishLaunching, this view would be added to the window:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Override point for customization after app launch
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
}

OK, but say you don’t even want to use nibs. Can you just create a UIWindow by yourself and make it key and visible? And can you specify an app delegate without a nib? Yes and yes.

Back in our Test application, delete the MainWindow.xib file completely. Also go into Info.plist and remove the main nib file entry. Then open up main.m

Remember when we called UIApplicationMain and we passed in two nil args at the end? Now we see what those are for. They are string representations for two classes. The first one is the principle class name. If you pass in nil, this will use UIApplication as the principle class. Unless you know enough about UIApplication to recreate it or at least subclass it, you probably don’t ever want to mess with this. The last argument is the name of the delegate class you want to use. Again this is a string. So, now that we’ve gotten rid of our nib, we can tell UIApplication to use our TestAppDelegate directly:

#import <uikit/UIKit.h>

int main(int argc, char *argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, @"TestAppDelegate");
    [pool release];
    return retVal;
}

So now we have our UIApplication instance and our TestAppDelegate instance. But we need our window. We can create this in applicationDidFinishLaunching. It usually looks something like this:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
	window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [window setUserInteractionEnabled:YES];
    [window setMultipleTouchEnabled:YES];
	[window setBackgroundColor:[UIColor whiteColor]];
    [window makeKeyAndVisible];
}

If you now wanted to add a view, you could do so something like this:

UIView *view = [[UIView alloc] initWithFrame:window.frame];
[view setBackgroundColor:[UIColor redColor]];
[window addSubview:view];

Well, hopefully that explains a bit about what happens when you fire up your app. And gives you a little more control and a few more options on how to do things.

6 responses so far

ASExpander updates

Nov 03 2008 Published by keith under Extensibility, Flash

Having too much fun with this.

* Changes:
* 1.1 Started using actionsPanel.getText, setText. And setSelection for cursor position.
* 1.1.1 Fixed a typo in enterFrame
* 1.1.2 Not correctly finding end of file if no cursor specified. So specified cursor at end of each snippet. Added some snippets.
* 1.1.3 Added help function. Type &help and run command and it traces out a list of commands.

http://www.bit-101.com/extensions/ASExpander.jsfl

Background in case you’re seeing this for the first time:

http://www.bit-101.com/blog/?p=1620
http://www.bit-101.com/blog/?p=1627

14 responses so far

ASExpander 1.1

Nov 02 2008 Published by keith under Extensibility, Flash

In the comments of my last post, James Thompson kindly pointed out that fl.actionsPanel has getText() and setText() methods, not to mention setSelection(). Thanks James! With this, I was able to get cursor positioning in there. Just put “&cursor” anywhere in the snippet, and with any luck, that’s where the cursor will go after the text replacement is done.

Got pretty messy doing that. The string in JSFL and the string in the editor return different values for getIndexOf() – seems to vary on newline characters. So I had to assign the text with the cursor info, get the index, replace the cursor info with nothing, and reassign the text. Also it wouldn’t find the &cursor string if it was followed by a newline either, so I’m just searching for &curso, which is pretty hacky but works.

Also slapped an MIT license in there and made it available for download.

http://www.bit-101.com/extensions/ASExpander.jsfl

Again, put it in your commands folder in Flash CS3 / CS4:

Mac: /[user]/Library/Application Support/Adobe/Flash CS3/en/Configuration/Commands
Windows: \Documents and Settings\username\Local Settings\Application Data\Adobe\Flash CS3\language\Configuration\

And assign a shortcut key to that command.

Also, check it out, we have video of it already!

http://www.video-flash.de/index/asexpander-code-snippets-in-flash/

22 responses so far

ASExpander : making AS3 in CS3/4 easier

Nov 02 2008 Published by keith under Extensibility, Flash

[Note: I just released version 1.1 of ASExpander. http://www.bit-101.com/blog/?p=1627 . This post is still worth reading for background and usage, but check out the other one for the latest version.]

There’s been a lot of talk about AS3 being “hard“. A lot of it stems around the fact that its is more verbose than AS1 or AS2. It just takes a lot more typing to do things that were really simple in earlier versions of Actionscript.

I’ve been using Flash CS4 a LOT lately, for spiking ideas, doing quick visual experiments, etc. In fact, the vast majority of stuff on my other site, Art from Code, is created directly in Flash CS4 right on the timeline.

So of course, I find myself typing a whole lot of the same few lines of code over and over (and over). The obvious solution was to use a snippets panel. Lee Brimelow has a nice one. http://theflashblog.com/?p=336

But that didn’t quite fit my workflow – making sure the panel is open, grabbing the mouse, clicking the item you want in the list, clicking the copy to clipboard button, clicking back in your code in the right place, and pasting.

One of the comments there mentioned that functionality like in Text Expander would be nice. I thought about it for a minute and realized that wouldn’t be too hard to do. And so I bring you ASExpander.

ASExpander is a simple JSFL command script. Save the following in your commands directory as ASExpander.jsfl:

[as]map = new Object();
map["&meta"] = “[SWF(width=800, height=800, backgroundColor=0xffffff, frameRate=31)]“;
map["&stage"] = “stage.align = StageAlign.TOP_LEFT;\nstage.scaleMode = StageScaleMode.NO_SCALE;”;
map["&resize"] = “stage.addEventListener(Event.RESIZE, stageResizeHandler);\nfunction stageResizeHandler(event:Event)\n{\n\ttrace(\”stage resize\”);\n}”;
map["&bitmap"] = “var bmpd:BitmapData = new BitmapData(800, 800, false, 0xffffff);\nvar bmp:Bitmap = addChild(new Bitmap(bmpd)) as Bitmap;”;
map["&enterFrame"] = “addEventListener(Event.ENTER_FRAME, enterFrameHandler);\nfunction enterFrameHandler(event:Event):void\n\t\n}”;
map["&mouseDown"] = “stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);\nfunction mouseDownHandler(event:MouseEvent):void\n{\n\ttrace(\”on mouse down\”);\n}”;
map["&mouseUp"] = “stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);\nfunction mouseUpHandler(event:MouseEvent):void\n{\n\ttrace(\”on mouse up\”);\n}”;
map["&mouseMove"] = “stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);\nfunction mouseMoveHandler(event:MouseEvent):void\n{\n\ttrace(\”on mouse move\”);\n}”;
map["&keyDown"] = “stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);\nfunction keyDownHandler(event:KeyboardEvent):void\n{\n\ttrace(\”on key down\”);\n}”;
map["&keyUp"] = “stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);\nfunction keyUpHandler(event:KeyboardEvent):void\n{\n\ttrace(\”on key up\”);\n}”;
map["&loop"] = “for(var i:int = 0; i < 10; i++)\n{\n\ttrace(i);\n}”;
map["&2loop"] = “for(var i:int = 0; i < 10; i++)\n{\n\tfor(var j:int = 0; j < 10; j++)\n\t{\n\t\ttrace(i, j);\n\t}\n}”;

_doc = fl.getDocumentDOM()
_tl = _doc.timelines[_doc.currentTimeline];
_layer = _tl.layers[_tl.currentLayer];
_frame = _layer.frames[_tl.currentFrame];
script = _frame.actionScript;

for(key in map)
{
script = script.split(key).join(map[key]);
}
_frame.actionScript = script;[/as]

Then, I HIGHLY recommend assigning a shortcut key to this command. I assigned Command-E, which overrides “Edit Symbol”, which I never use anyway.

Now I can just type:

&enterFrame

hit Cmd-E, and I have an enter frame listener set up. Notice that my hands never left the keyboard!

It’s easy to add your own snippets. Just give it a token and text:

[as]map["token"] = “text to replace token with;”;[/as]

If you’re not a coder, get one to write some useful snippets for you and put them in string format. They’ll know what to do.

I’ve gone with an ampersand (&) prefix just to avoid possible conflicts with other code in the script. You might have a “enterFrame” in your code that means something, but probably not a “&enterFrame”. But that’s not built into the command at all. If you don’t like the ampersands, change them to %s or *s or !s or just use straight text if you are brave.

Anyway, hopefully this makes AS3 a tiny bit less painful for a couple of people. Let me know if it helps.

21 responses so far

CS4 MetaData JSFL Script

Oct 27 2008 Published by keith under Extensibility, Flash

It’s been a while since I’ve done much with JSFL, but I’ve been playing with CS4 a lot more than I did with CS3. One thing I love is the ability to set SWF MetaData right on the timeline. I find myself typing in a line of metadata when it would probably be easier to go to the Properties Panel and set the SWF size there. But I’m usually in the Actions Panel with my hands on the keyboard and it just comes quickly.

But I realized I could make it even quicker and wrote the following very simple JSFL script:

[as]_doc = fl.getDocumentDOM();
_tl = _doc.timelines[0];
_layer = _tl.layers[0];
_frame = _layer.frames[0];
headerText =  “[SWF(width=800, height=800, backgroundColor=0xffffff, frameRate=24)]\n”
headerText += “stage.align = StageAlign.TOP_LEFT;\nstage.scaleMode = StageScaleMode.NO_SCALE;\n\n”;

_frame.actionScript = headerText + _frame.actionScript;[/as]

This also sets some common stage properties. Just throw that in your Commands directory in Flash CS4′s Configuration directory. I set up a keyboard shortcut for it: Cmd-Opt-M (for MetaData). Now, with a quick keystroke, my movie is set up the way I want it.

I’m using a very inflexible method of finding the current frame: current document, scene 0, layer 0, frame 0, because that’s where my code always is. You can certainly mess with that to make it more robust if you need it. I started making a SWF Panel that would let you set the dimensions, frame rate and background color with some controls, and then a button to add the code to the frame, then I realized that was pretty stupid, because if you are going to go through the trouble of doing settings and pushing buttons, you might as well just use the Properties Panel. :)

No responses yet

flashextensibility.com relaunches!

Jul 04 2006 Published by keith under Extensibility

A couple of years back (wow, was it so long ago already?) while I was writing the book Extending Flash MX 2004 with Todd Yard, I registered the domain name, flashextensibility.com. I had a site up there for a while with info about the book, a forum, and a repository of extensions, not only from the book, but submitted by others as well.

As time went on though, I drifted away from the extensibility scene and the site got kind of stale. A few months back I decided to give it up and let someone else have it. Peter Elst stepped forward. He was the technical editor for the book, and knows the subject well, so I was really happy to hand it over to him.
After a short break, the site is now back on line with some nice extensions up. I plan to add a bunch myself. If you use the Flash IDE at all, you’re definitely going to find some good stuff that will speed up your workflow. Do yourself a favor and check it out:

http://www.flashextensibility.com/

2 responses so far

And the FlashExtensibility.com winner is…

Jan 28 2006 Published by keith under Extensibility

Peter Elst!

Peter contacted me after yesterday’s post and I transferred the domain over to him. I’m thrilled that he was the one to get it. He was the technical reviewer for Extending Flash MX 2004, and has a great knowlege of and interest in the extensibility layer of Flash. I’m sure tht he will do cool things with the site, hopefully even fullfilling the original vision I had for it.
www.flashextensibility.com

No responses yet

Into JSFL? Want www.flashextensibility.com ?

Jan 27 2006 Published by keith under Extensibility

So a couple of years ago, Todd Yard and myself wrote the book Extending Flash MX 2004. It’s a good book on the subject. Really the only book on the subject (other than a Macromedia Press one that is just a print out of the JSFL help files).

Just before the book was published, I registered the domain www.flashextensibility.com . The idea was to put up a library of cool extensions, a forum for answering questions, and so forth. Well, life went on and I drifted away from JSFL except when I really needed it for something, and the site has pretty much died. I recently found out that the forum had been hacked, so I took that down. (damn PHPBB!)

So rather than continuing to pay monthly for a site that I, myself, haven’t visited in probably half a year or more, I’m letting it go. If anyone wants the domain, get in touch and we’ll work out transferring it to you. I’m not even trying to sell it. You can have it. I’d just like to see it go to directly someone who wants it rather than get it snatched up by someone who will try to make a profit off of selling it to someone else.

5 responses so far

PB & JaM

Apr 23 2005 Published by keith under Extensibility, Flash, General

Well MTASC seems to be the buzziest technology in the Flash world these days. Jester just coined the acronym FAME – Flashout, Eclipse, ASDT, MTASC. (I know he didn’t come up with the process, but I think he was the first to acronymize it.) While I’m sure the Eclipse route is great, I myself couldn’t be pried from PrimalScript, and have already posted my workflow here in a couple of other posts. Not to be outdone on acronyms though, I came up with one that describes my setup: PB & JaM: PrimalScript, Batch-files, JSFL and MTASC!

One thing I’m loving about the batch file approach is how you can customize your compile, even compiling and running multiple swfs. For instance, I’ve blogged about other solutions where I need to compile a swf, then compile another swf and load the first into the second. With MTASC this is such a breeze. You just write your batch file so that it compiles the loaded swf, then compiles the loader, and then, only if everything compiled ok, it runs the loader swf. In fact, in many cases, I don’t need to compile both, so I just comment out the line for the one I don’t need to recompile. Thus the batch file becomes sort of a make file.

Another thing I just saw and I’m going to try to fit into my flow is this swfmill xml generation tool. Since this is all command line stuff, it should be able to be dropped right into my batch file. I’m liking where this is going.

5 responses so far

MTASC and PrimalScript

Apr 19 2005 Published by keith under Extensibility, Flash

I’ve been testing out MTASC recently. I started trying to use it for some large projects, but was running into a learning curve on getting all the class paths and so forth all in a row. I had deadlines and couldn’t afford to mess around with it, so shelved it for a while.

But now I have a little time on my hands and jumped back into it. One of the biggest annoyances was trying to fit all that stuff on the command line. I have a few different class paths going on, and my command line was getting rather long. Of course I was putting it in a batch file, but it was still getting unweildy.

So I dug up some old batch file tricks and got it down to a system.

I use PrimalScript, and found that it integrates quite well with MTASC. I got a few tips from Robert Penner the other week in Toronto as well. Here’s the flow:

1. In PrimalScript, go to Tools/Options/Environment/Languages/ActionScript. In the “Selet a Category” dropdown, choose “Script Interpreter”. In the box below that, enter “$ProjectFolder$\compile.bat” (without the quotes). Also check “Capture Output” at the bottom of the dialog.

2. Now when you make a project, create a new text file named “compile.bat” in the root of the project directory. Now, when you hit F7 while in a project, this compile.bat file will execute. You have a couple of choices here. If you want the Flash IDE to compile whatever fla file is open, you can add the following to your compile.bat:

@"c:Program FilesSapienPrimalScriptFlashDriver.exe" compile.jsfl

But, if you want to use mtasc instead, here’s what you put in compile.bat:

@echo off

set cp1="c:Documents and Settings\Local SettingsApplication DataMacromediaFlash MX 2004enConfigurationClasses"
set cp2=
set cp3=

set swf=..deploymyapplication.swf
set class=MainClass.as

mtasc -cp %cp1% -cp %cp2% -cp %cp3% -mx -swf %swf% %class%

if errorlevel 1 goto end

%swf%

:end

What this does is set variables for as many class paths as you want, a variable for your main swf and main class. It then uses these variables to compose the command line. Finally, it checks the return value of the call to mtasc. If it compiled successfully, this will be 0, and the batch file will load the swf. If not, it will jump to the :end label and display whatever error it ran into. The cool thing is that you can then double click on that error line and PrimalScript will open up the offending .as file and go right to the problem line!

Note that you can include just a single class path (or none) or as many as you want. Just set the variables and alter the command line as appropriate. Also notice that you can use file paths to your swf. I publish mine in a deploy directory on the same level as my source directory (which is where my project is). So my swf variable is ..\deploy\myapplication.swf

When you’ve got it how you want it, hit F7 and there’s your swf! (or your error message.)

Third Party Components.
I don’t use MM components. I use the BeamJive Bit components (which I made). At first I was having a lot of problems with these in mtasc. If you use the MM components, the -mx switch takes care of you. If you are using a third party set like this, or custom components you have made, you need a path to the class files, or at least the intrinsic files. The BeamJive set does install intrinsic class files. I think the default path is the same as the first class path listed above. But I’ve put mine in another location, which I use my second class path for.

Even if you have the class paths for your components set up correctly, you may still get warnings. This is because sometimes the components use other sub-components, whose classes are not directly referenced in your swf. The easiest way I’ve found to handle that is just to copy the class paths from the warning messages and add them as import statements in your main class. Even though that class may not use them directly, they will be included in the swf and handle any warnings or errors.

Under informal testing, I had a fla that takes 7 seconds to compile in Flash. With the above setup, it’s somewhere around 2 seconds. Too quick to measure exactly.

4 responses so far

Older posts »