This is the third post of our Translating between ActionScript and Objective-C series and the first one in which you will get your hands dirty with code.
What was covered so far?
- We started with an introduction of what to expect from the series and how tutorials will be structured
- Then we laid some ground work and saw how ActionScript data is represented in C
What will this part cover?
In this and the next four articles you will start by building an arsenal of auxiliary functions that turn lengthy Objective-C code into one-liners that you can reuse in the native part of your iOS ANEs. Code you will write will be Objective-C and will go into the Objective-C library that’s part of your ANE.
The goal of this article is that you end up being able to send an event to ActionScript with this short line of code:
1 |
sendMessage( MSG_ERROR, @”An error happened” ); |
Sending events to ActionScript
Sending an asynchronous event is one of the three ways of passing data from native code back to ActionScript. Have a look at this post for the other two ways.
Sending an event is the only asynchronous way of passing data back and the only C API AIR call you can make on any thread other than the main one. It is your way of signalling to your ActionScript code when something has gone wrong or when the result of an asynchronous operation is ready, for example retrieving user names from a server.
What effectively happens is this:
1. You subscribe to status events delivered to your ExtensionContext instance in ActionScript:
ActionScript
1 2 3 4 5 |
m_extensionContext.addEventListener( StatusEvent.STATUS, onStatusEvent ); ... private function onStatusEvent( _event : StatusEvent ) : void { trace( _event.code ); trace( _event.level ); } |
Objective-C
1 2 3 |
FREDispatchStatusEventAsync( ctx, ( const uint8_t * ) "This is the message CODE", ( const uint8_t * ) "This is the message LEVEL" ); |
1 2 3 |
FREResult FREDispatchStatusEventAsync( FREContext ctx, const uint8_t* code, const uint8_t* level ); |
For this purpose you will need your auxiliary function to have access to a context instance. I tend to make a copy of the one passed to the extension context initializer and keep it in my ANE’s main native file as a global variable. Makes sense to use that instead of having another copy lurking around. In the declaration below the extern keyword makes that global copy available to the code in the file where you are building your reusable library of functions:
1 2 |
#pragma extern declarations extern FREContext g_ctx; |
Since we are in a declaring mood (or is it just me?), let’s declare a few event types too:
1 2 3 4 |
#pragma event types const NSString * MSG_ERROR = @"ERROR"; const NSString * MSG_WARNING = @"WARNING"; const NSString * MSG_INFO = @"INFO"; |
And finally, here is the auxiliary function you have been waiting for:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#pragma sending events to ActionScript /** * Sends a flash.events.SatusEvent to ActionScript. * The dispatch happens asynchronously. * * @param message Type This will be mapped to StatusEvent's code property. * * @param message This will be mapped to StatusEvent's level property and * can contain any information about the event in string form. */ void sendMessage( const NSString * const messageType, const NSString * const message ) { // Having a messageType is important, but the message itself can be left empty. static const NSString * MSG_DEFAULT_EVENT = @"STATUS_EVENT"; assert( messageType ); if ( NULL != message ) { FREDispatchStatusEventAsync( g_ctx, (uint8_t *) [messageType UTF8String], (uint8_t *) [message UTF8String] ); } else { FREDispatchStatusEventAsync( g_ctx, (uint8_t *) [MSG_DEFAULT_EVENT UTF8String], (uint8_t *) [messageType UTF8String] ); } } |
Result
Now you can do this much shorter call in any part of your code:
1 |
sendMessage( MSG_ERROR, @”An error happened” ); |
Additional information
- If you are wondering what’s with all those assert statements in the code above, check this short post: Asserting your way in ActionScript and Objective-C
- A reminder about what all of those pointers and non-ActionScript concepts mean: how ActionScript data is represented in C
What’s next?
Our next article will show you how to implement a one-liner for one-liner for checking FREResult. See you there!
Leave a Reply