Archive for the 'iPhone' Category

[UIImage imageNamed:] is a memory leak, but only on 2.x

Update: I was contacted by an Apple engineer saying this bug was fixed in 3.0, and asked if I could reproduce it there. I tried my sample project again, and I was unable to reproduce it on 3.0. This problem only seems to affect 2.x devices.

Not too long ago I was profiling an iPhone app that I had written for a client. Their testers had found that using a certain feature for long enough ended up causing the app to be ejected because of a low memory situation.

After some quality, yet painful, time with Instruments I discovered I was never deallocating image memory in the form of CGImageRef and its internal drawing cache. (It turns out that if you draw a CGImageRef while on a thread other than the main thread, it creates a cache of the bitmap data. However, this wasn’t my problem.)

At first I thought I simply forgot to release the UIImages somewhere. I put in some logging code and was able to confirm that I was releasing the UIImages the correct number of times, in the right places. But it appeared that someone had called retain on it an extra time.

That’s when I happened to notice that only the UIImages I had constructed with imageNamed: were failing to be released. I suspected that they were being retained in a global cache. The only problem with this cache is not released in low memory situations. Even when my app receives a low memory notification and I free up all the memory I can, the UIImage global cache just sits there clutching it’s unused UIImages to its chest, muttering.

Unfortunately for me, some of the UIImages I was loading were large, and I was expecting them to be deallocated when I released them. As the feature was used, different UIImages were loaded with imageNamed: and never released until the phone ran out of memory and my app was ejected.

The solution was to write a replacement method for imageNamed: that didn’t cache the UIImage. Here’s what it looks like:

@implementation UIImage (OrderNDev)

+ (id) imageNamedNoCache:(NSString *)name
{
	NSString *basename = [name stringByDeletingPathExtension];
	NSString *extension = [name pathExtension];
	NSString *path = [[NSBundle mainBundle] pathForResource:basename ofType:extension];
	return [[[UIImage alloc] initWithContentsOfFile:path] autorelease];
}

@end

The moral of the story is imageNamed: is only for use with small images that are used constantly throughout the app’s lifetime. Don’t use imageNamed: if you want that memory back on a 2.x device. Everything will work fine on a 3.x device though.

Experiences with a Sound Designer

The last time I spoke of my upcoming iPhone game, I was soliciting recommendations for graphics and sound designers. Since then I’ve hired a sound designer and had the sounds completed. I had originally intended to write about my experiences with sound and graphics designers in one article, but I actually just hired a graphics designer, so my experiences with him will have to wait until next time.

This is a description of my experiences with finding and hiring a sound designer to create royalty free, custom sound effects for my game. My experience with hiring and working with a sound designer was quite pleasant. The entire process was completed exactly one week after I first started contacting designers.

Preparation

Before I started contacting designers I sat down to figure out what exactly I needed from the sound designer, and what information he or she would probably need from me. I’ve never worked with sound designers before, so I had to make some educated guesses. In the end, my guesses seemed to be at least adequate. I wrote down everything I thought the designer would need in a specification document.

The specification document I create was pretty simple; it had two sections: an introduction and a description of the sounds. In the introduction I gave a brief overview of the game, how the sounds were going to be used, the “theme” I wanted, and a total count of sounds to be created. I managed to fit this into five sentences, on the assumption that the designer wanted to know about the sounds, and not my life story, fascinating as it is.

For each of the sounds, I created a description for it. I gave each sound a short, unique name so they were easy to refer to. I then described what the sound was, for real world sounds (e.g. card placed on a table), or what I wanted it to sound like, for abstract sounds (e.g. a sharp, clicking sound). I also tried to give the context in which the sound will be played (e.g. when a button is pushed). Finally, I stated the length I wanted the sound to be. Most of mine were only one or two seconds in duration.

Selecting the contestants

With the sound specs in hand, I was ready to start contacting designers. The only problem was that I didn’t know any, nor had I heard of anyone recommending any. Being put in such a desperate situation, I did what any engineer would do — I googled for some, and blogged about it. In the end, I contacted three different sound designers:

I originally found about six companies that I thought could possibly do the work, but I whittled down the choices to these by using the following criteria:

  1. Did it look like the designer had experience creating sound effects for games? Since that was what I wanted, it made sense to see if their portfolio reflected that.
  2. Could I navigate the designer’s site well enough to actually find a way to contact them? I didn’t originally intend for this be criteria, but it ended up being one. Advice for sound designers: hire a good web designer.

For each of the three designers I selected, I sent out an introductory email. In the email, I briefly described the project and asked if they were available and interested. I mentioned that I had a spec and would like a rough estimate before work began. In retrospect, I should have probably attached the sound specification to the introductory email, because that was the first thing everyone who was interested ask for.

Of the three designers I contacted, SoundRangers and IndieSFX replied to me within 24 hours. Sound for Games never got back to me. SoundRangers and IndieSFX charge by the sound, and offer both stock and custom sounds. For stock sounds, prices range from around $1 to $5 per sound, although IndieSFX only sells them in packs. For custom sounds, prices range from $10 to $40 per sound. None of the stock sounds were quite what I wanted, so I elected to go for all custom sounds.

Between SoundRangers and IndieSFX, I chose IndieSFX. Both seemed to be comparable in quality, but IndieSFX had better prices.

Creating the sounds

Once I had signed a contract for IndieSFX to create the sounds, I began working with Mark to do just that. Based on my specification, Mark created a first draft of the sounds by the next day. Some sounds had multiple variations for me to pick from, while others I was just given one choice to refine.

Mark and I went through about seven or eight different variations of the sounds before we settled on something. In general, I got a new revision of the sounds every day, which was highly motivating.

Along the way I learned a couple of things about sound. First, there’s the concept of “wet” versus “dry” sounds. Wet sounds have more echo and reverb and, at least in my case, sounded better. Dry sounds are shorter, which can be good if you have a tight time interval in which to play a sound. Second, I found out that playing the same sound several times in a row makes it sound like a typewriter or machine gun. Fortunately Mark knew how to fix this: create several variations of the sound and randomly pick a different one to play each time.

That leads me to something I learned about the process: always try out the sounds in the game. Sounds that sound great by themselves may not sound good in context, or when they’re interacting with other sounds. I unfortunately approved a couple of sounds that didn’t actually work well in the game. Fortunately Mark was nice and let me make changes even after I initially said they were OK.

The other thing I learned was that I needed to be as specific as possible when I wanted changes. It was easy to verbalize emotional reactions to sounds (I like this, I don’t like this, etc), but hard to spell out specifically how I wanted something changed, so Mark could actually do it. It turns out sound designers aren’t mind readers. Who knew?

After about a week of revisions, I had sound effects I was happy with. I paid IndieSFX, added their name to the about box, and checked the sounds into source control.

Using the sounds

During the creating process, I was taking the sounds Mark was sending to me and integrating them into my iPhone game. Since Mark was sending me uncompressed WAV files, I had to convert them before I could use them. Fortunately, Apple provides a nifty little command line tool to do just that: afconvert.

At first I was keeping the sounds uncompressed, for quality reasons, so I used afconvert like this:

/usr/bin/afconvert -f caff -d LEI16 <input WAV file> <output CAF file>

Unfortunately, high quality, uncompressed sounds are huge and this app is going to be distributed over the internet. So I switched to a compressed format, using this command line:

/usr/bin/afconvert -f caff -d 'ima4' <input WAV file> <output CAF file>

This gave me a 50% savings in size, with no discernible difference in quality. I chose these formats because I needed the sounds to be able to play simultaneously, and these are the two formats that the documentation say will allow that.

Lifting the veil

Hopefully this article has made the process of working with a sound designer more transparent. When I started this process, I had no idea what to expect — how much it would cost or how the process even worked. But I was quite pleasantly surprised. Getting custom sound effects created for an indie game is quite reasonable, both in time and money.

How to fix the App Store without Neutering it

As I see it, the App Store has three main problems. One of them is a customer’s concern, and the other two are developer’s:

  1. Customers hate paying for crappy applications.
  2. Developers have a hard time getting exposure for their apps.
  3. Developers want high enough prices to support development of their applications.

Identifying these as problems isn’t exactly a revelation, but I want to state them clearly. That way, when I examine potential solutions, I can see how well a given solution solves them.

Customers care about revenue, right?

A common solution that has been bandied about is the idea of changing the application ranking algorithm. Right now, applications are sorted based on how many people have bought it, which strongly favors the $0.99 applications. The “fix” is to rank applications by revenue. The logic is that by incorporating the price of an application into the ranking algorithm, it won’t be so biased towards $0.99 applications, and higher priced applications can flourish.

From what I’ve heard of this argument, it is attempting to fix both developer problems: non-$0.99 applications would get more exposure and applications can have higher price tags.

Unfortunately, this solutions fails the test for a number of reasons:

  1. Sorting by revenue heavily favors large companies who produce blockbuster applications, such as Sega with Super Monkey Ball. Since they are well known, they can charge more and still sell a lot. This solution effectively squeezes out any small companies, or anyone with a niche application.

  2. This solution only helps the top 100 revenue earners. Everybody else is still screwed. A solution that only fixes the problem for a small fraction of the developers isn’t really a solution.

  3. Any ranking algorithm, no matter how complex, can be gamed. If an app is in the top 100, it makes an enormous amount of sales. That’s a lot of incentive to game the system.

  4. The solution not only doesn’t address the customer’s concerns, it serves to confuse the customer more. What customer asks how much revenue a product generates, when deciding on a product of any kind? It is possible they might ask what the best selling one is, with the thought that it’s popular because it’s good or at least safe.

    Since this solution hurts the user experience, it’s pretty much DOA. Apple isn’t going to change the App Store to make it more difficult to use, even if it does help a few developers.

I think the proponents of this solution want it because it sounds like a quick fix that will at least shake up the top 100, and maybe give them a chance to squeeze into it. While I can sympathize with the desire to get more exposure, this solution doesn’t actually fix the problem and only serves to make things worse for users. But before I talk about another solution, I want to talk about the problem of getting exposure for an application.

Fixing the wrong problem

So the deal is the App Store can’t actually fix all three of the problems I mentioned. Specifically, it can’t fix developers not getting enough exposure for their applications. I know that Apple said they’d take care of all the marketing of iPhone applications when the store launched, but it’s time to face the fact that they can’t and won’t. Apple won’t feature all apps on the front page, and even if they tried, they could only do each one for a short amount of time. It’s simply not enough to bring in a sustainable stream of customers.

This has parallels in the real world. A store, such as Target, may advertise products it sells, but only certain ones and only for a certain amount of time. The manufacturer also must do some advertising in order for people to become aware of the product and actually buy it. This is true for all products, including the $0.99 a pack chewing gum that’s next to the checkout lane (the real world’s version of the top 100 apps).

Developers are too wrapped up in getting on the top 100 as a means for getting exposure. Everybody wants their product next to the check out lane, but the reality is only a few cheap, impulse buy type of products will ever make it there. All the other products are going to be out in the store aisles, where customers will have to be looking for them to find them.

The bottom line is that finding customers for your application isn’t a technical problem, and a technical solution isn’t going to fix it. It is a marketing problem, and it requires marketing to fix it. Since developers can’t count on Apple doing the marketing, they need to do it themselves. I know that’s scary news to those of us who have only ever been engineers, but we need to acknowledge it and work through it.

Taking a test drive

Now that we’ve learned that getting exposure for an application isn’t a problem the App Store can fix, I want to focus on the remaining problems it can fix. Another solution that has been proposed is the now ubiquitous (on the desktop) try-before-you-buy model. The idea is simple: a potential customer can download an application for free and use it for a set amount of time, say 30 days. At the end of the 30 days, the potential customer can either buy it or it’s deleted from their phone.

This solution, while more complicated than the ranking solution, actually solves the problems:

  1. Because the customer gets to try out the application before buying it, they don’t have to worry about paying for a crummy application that doesn’t solve their problem.

  2. Since customers can try out more expensive apps without risk, they are more likely to buy the more expensive application, since they can figure out if it’s worth the price or not. This allows more expensive apps to survive in the App Store.

As an added bonus, the top 100 becomes more accurate because only the apps that users actually think are worth something increase in rank, instead of apps that had the best screenshots or descriptions.

The thing to remember is that the App Store is still young and still maturing. While it is different from other markets, it’s not that different from the desktop market or the other mobile markets. People still want to try out applications before they buy them, and developers still need market their products if they want someone other than their mother to know about them.