Showing all entries for: June 2011

Support Your Favorite Apps Today

It’s simple:

On your iOS device, go find all of your apps that you downloaded in the App Store, and leave an honest review. Right now, I think the review system is a little flawed. People generally don’t think to write a review unless they had an extremely bad experience. The Write a Review form seems to be more like a Leave a Complaint form.

Admittedly, it’s a tough problem to solve.

One way I think they could solve the “problem” is start all apps at 5-stars, and then calculate a final star-rating based on the amount of downloads, taking into consideration all the positive and negative reviews. The algorithm could assume that an app is absolutely stellar if it has tons of downloads and relatively few bad reviews, instead of averaging between the amount of positive/negative reviews—which is the way it seems to be working now.

So while the review system is still flawed, let’s all set aside some time to revisit the apps we have downloaded in the App Store and let the developer know what you think in the form of a review (if you haven’t already).

Hi-Jack Optimizations (aka "Sub-Classing")

Did you know that you can take control of just about any of the Corona SDK’s pre-made functions attached to display objects?

That’s right, you can actually replace some of the built-in functions with your own. This is known as hi-jacking, and it can come in very, very handy in many instances.

There’s one little performance (or even better, crash-prevention) “trick” I’m going to show you that will involve hi-jacking Corona’s built-in removeSelf() method that’s attached to every display object.

Here’s the code:

local myObject = display.newImage( "myimage.png" )
myObject.x, myObject.y = 100, 200

local myObject:enterFrame = function( event )
    print( "This is your runtime listener!" )

Runtime:addEventListener( "enterFrame", myObject )

-- The line below will "cache" the original removeSelf function
-- so it is still able to be used:
myObject.oldRemoveSelf = myObject.removeSelf

-- Let the hi-jacking begin:
function myObject:removeSelf()

    -- new stuff we're adding:
    Runtime:removeEventListener( "enterFrame", self )

    -- call the original removeSelf() function:
    myObject = nil

See the above code with syntax highlighting here.

If you go line-by-line, you can probably figure out what I did. I “hi-jacked” the built-in removeSelf() function for myObject, and added a call to Runtime:removeEventListener() before proceeding to call the original removeSelf() function.

Of course, it’s just a simple example, but you can probably see where the above might come in handy. Runtime listeners must be removed manually, as I describe in both my managing runtime listeners and memory 101 articles.

However, sometimes Runtime listeners are hard to keep track of (especially if your app is a significant size), and if you have a lot attached to objects (as I do in the example I gave above), some might slip through.

The above “hi-jacking” example basically makes sure the associated Runtime listener is removed along with the object whenever you call removeSelf(). It’s very handy!

I’ve used hi-jacking plenty times to add to plenty of Corona’s built-in functions. What other hi-jacking uses, besides cleaning up Runtime listeners, can YOU think of?

To Return True, or Not To...

…THAT is the question. Before I get started, have you ever found yourself in any of the two undesired situations below (if you intended them to happen that way, then this article is not for you):

  1. You add a touch listener to two different objects, and at some point in your app, the two objects overlap. When you go to touch the object on top, the “began” phase fires on it, but then the object underneath also receives the touches.

  2. You have a ui.lua button that happens to be above another object or group that can also receive touch events, and the same situation above happens—only your button “sticks” and is rendered useless for the duration of your app’s runtime.

Do you want to know a quick, one second solution to BOTH of those problems? How’d I guess :–)

Solution to situation #1: In your touch event listener function, make sure that you are returning true (e.g. via a “return true” statement).

Solution to situation #2: In your event listener you specified for your UI button, ditto above.

And there you go, problem solved. This little tip has saved me lots of frustration, stress, time, and the list goes on.

And now for the explanation. When it comes to “touch” events, if the listener function returns true, then that indicates that your touch target was intended and stops there. If it returns false (or nil—in other words, you didn’t tell it to return anything), then the touch will pass through that object and enable touches behind it.

In that situation, if there’s something that has a touch listener assigned to it behind the object you intended to touch, then that object will also receive touch events. The unfortunate thing is, the first object you touched will only receive a “began” touch phase, and not an “ended” phase (which explains all the crazy behavior of ui buttons in this situation).

And there you have it, another life-saving tip for you to put in your “Corona/Lua Toolbox” for those late-night coding/tempted-to-rip-your-hair-out-of-your-head sessions.

And speaking of “late night” … I need to go to bed.