Archive for May, 2009
Beginning iPhone Dev for Rubyists in T.O.
Friday, May 29th, 2009
Dan Grigsby, over at Mobile Orchard, is going to be running a two day course on Beginning iPhone Programming for Rubyists in Toronto in July. He’ll be in Toronto for the FutureRuby conference and he’ll be running his class just prior to the conference. You can find out details here:
- Beginning iPhone Programming for Rubyists (www.mobileorchard.com)
Dan’s the guy who interviewed me on the Mobile Orchard podcast. Dan seems like a cool guy, so if you’re a Ruby developer in Toronto with an interest in iPhone development, check out the web page and see if the course might be something that’s up your alley.
Owen
Dapple 1.2 and NSString Leaks
Wednesday, May 27th, 2009
Dapple 1.2
I haven’t been posting very frequently lately, mostly because I’ve been working very hard to get this Dapple 1.2 update out the door. I’m thrilled to announced that I submitted it this afternoon! Dapple and Dapple Lite 1.2 were both submitted today. If everything goes according to plan, they should be available around this time next week.
The update is quite exciting, in that it adds support for global high scores lists! Now you can see how your top score compares to other people around the world! With the update you’ll be able to see your score and the 9 people ranked directly above you, or look at the top overall scores. It’s already been exciting watching the testers’ scores roll in. I can’t wait to see how everyone does!
Dapple Lite also allows you to submit your scores online, but you’ll be using the same scoreboards as those with the full version. If you want to get near the top of the scoreboards, you’ll have to buy the full version.
There are also a few user interface tweaks that I’ve made and also a few little fixes. Finally, there’s also a feature for a top secret project I’ve been involved in. You’ll have to wait for the update to find out what it is!
Leaderboards
Now I want to talk a little bit about the technology that I used for the high scores lists and then talk about a nasty memory leak I tracked down today before submitting. If you’re not interested in this kind of thing, I’ll forgive you if you want to stop reading now…
When I started thinking about implementing the leaderboards, I first looked a few existing technologies, hoping that I might be able to just “drop something in” and it would work. There are a few technologies out there that looked like the might be able to do that. Where they fell short, however, was in my ability to completely customize how I wanted to store the data and display it. Plus, I thought it would be fun to write my own system.
When I started reading up on the Google App Engine, I was convinced it would be easy to set up a server back-end using that, and I was right. Using the App Engine, I had the server-side working in about 3 days of work (and that included learning Python and how the App Engine works). It’s really easy to get things running with their system.
What took time, as usual, was the user interface. I had considered creating an in-game web view that would load a web page that had the high scores on it, but I decided (perhaps somewhat foolishly) that I didn’t want the player to have to leave the look and feel of the game. I decided to build it using my existing UI framework. This only caused a few problems, mostly around trying to find space to fit all the data. However, I also ran into some nasty string memory stuff in the code I wrote to parse the data coming from the server.
I encountered a memory leak this morning that I want to share with you, because it’s not immediately obvious why it’s a leak. When I get my data from the server, it comes in as a long string of data. I use NSString’s handy methods to chop it up and stuff the results into a dictionary, then I shove those dictionaries into a big array. Here’s a bit of the code that had the mem leak:
NSArray* recordData = [[records objectAtIndex:i]
componentsSeparatedByString:@","];
NSString* username =[[NSString alloc] initWithString:
[recordData objectAtIndex:0]];
...
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:username forKey:@"name"];
...
[mCachedGlobalHighScores addObject:dict];
[username release];
This causes a memory leak that is caused at first line of code. I was baffled by what was causing this. The memory leak seemed to be happening on the string inside [recordData objectAtIndex:0] but I couldn’t figure out why. I asked around on Twitter and many people pointed me to the method [myObj retainCount] that allows you to see how many retains have been made on an object. BunnyHero pointed out that you can run this from the GDB command prompt when stopped at a breakpoint: ‘print (int)[myObj retainCount]‘.
I set breakpoints on the line where username is allocated, and on the line after. When execution halted just before username was allocated, I checked the retain count on the object at index 0. It was 1. This was expected. However, right after username was allocated, it became 2! Why was allocating a new string using initWithString (which is supposed to copy the string and create a new object altogether) increasing the ref count?!
I think it had something to do with the fact that the NSArray is storing the values as type id, not NSString. When you do an initWithString, I think it was just copying the pointer, and doing a retain, so the new object allocated memory, but pointed to the same object. So, in order to fix that, I had to do this instead:
NSArray* recordData = [[records objectAtIndex:i]
componentsSeparatedByString:@","];
NSString* username =[[NSString alloc] initWithFormat:@"%@",
[recordData objectAtIndex:0]];
Now the memory leak no longer happened when recordData was created…it happened when username was created! But that’s ok, now at least the leak is happening at a more reasonable place.
So now I looked at where I was cleaning up my big array of cached data:
[mCachedGlobalHighScores removeAllObjects];
Reading the docs, removeAllObjects is supposed to call release on each removed object. I assumed that would do a deep release. Not the case. So I tried this instead:
for (int i = 0; i < [mCachedGlobalHighScores count]; i++)
{
NSMutableDictionary* record =
[mCachedGlobalHighScores objectAtIndex:i];
[record removeAllObjects];
}
[mCachedGlobalHighScores removeAllObjects];
But that still didn’t work. The username string wasn’t been released! So finally, I did this:
for (int i = 0; i < [mCachedGlobalHighScores count]; i++)
{
NSMutableDictionary* record =
[mCachedGlobalHighScores objectAtIndex:i];
NSString* name = [record objectForKey:@"name"];
[name release];
[record removeAllObjects];
}
[mCachedGlobalHighScores removeAllObjects];
And it works! You might be asking why I didn’t do an autorelease on the username NSString. I tried that. It worked most of the time. But if you flipped back and forth on the screen quickly (causing everything to delete and recreate quickly), I found that I could get into situations where sometimes that string wouldn’t release at all, causing a leak. I decided that if I managed the memory myself, at least I’d know what’s going on.
So, the lessons are:
1) If you are dealing with a string that’s stored as type id, make sure you’re careful about how you use it to init new strings.
2) When you alloc (or retain) you have to release. (Yes, I know that should be obvious by now, but sometimes you think a built-in method is releasing or retaining when it isn’t).
Well, apparently I’ve decided to make up for a lack of posts with one gigantic post. Look for more news on the Dapple 1.2 update when it gets approved. And keep your eyes and ears open for news on that secret project I may or may not have mentioned…
Owen
Meet-Up Thoughts and Dapple Update
Friday, May 15th, 2009
Is everyone (in Canada) ready for the long weekend? I know I am! I thought I’d write a post before I head up to my parents’ cottage for the weekend, where I won’t have a computer, let alone access to the internet.
Wednesday night we had the 2nd Toronto iPhone Developer Meet-Up, which was a great success in my mind. We had two great presentation by local iPhone devs. James Eberhardt was able to secure us space at the Rich Media Institute, which turned out to be perfect. There was beer that could be bought, and we had a great conference room with a projector for the presentations. I’m extremely pleased with where the meet-up seems to be heading. I think everyone who came, that I talked to, enjoyed the format. I think we’ll try to stick with the format of two short (15 mins or less) presentations, followed by socializing and drinks.
If you missed the meet-up, the presenters have graciously posted their presentation slides on their sites.
- Rules You Should Break in the App Store (www.xinsight.ca – PDF) – Jason Moore from xinsight gave a presentation on tips and tricks for making the most of the App Store.
- iPhone + Box2D (blog.zincroe.com) – Luke Lutman from zinc Roe Design gave a presentation on using the open source Box2D physics engine with iPhone. He has posted his short presentation slides (that we saw) as well as a longer presentation and an example source code project.
A big thanks to both presenters! It was a great way to kick off the new format for the meetings. I think everyone enjoyed it.
If you haven’t already, please join the Facebook group for the meet-up. It’s called Mobile Developer & Designers of Toronto. I look forward to seeing you in June!
As I mentioned previously, I had be writing a chapter for a book on iPhone development. I’m pleased to say that I submitted my first draft to the publisher this week. As such, I was able to do some coding towards the end of the week. Yay!
I started working on stuff for the Dapple 1.2 update. The biggest new feature will be the inclusion of world-wide leaderboards for the game. I’ve decided to use Google’s App Engine as the server-side technology, as it scales nicely and it means that if I did somehow introduce some kind of server-side security flaw (which I don’t think I have), it’s not running on my own web server.
I’m two days into things and I’m quite impressed with the App Engine stuff. Sure, I had to learn Python pretty quickly, but at this point the server-side stuff is pretty much done. I’m sure it will need some tweaking once I actually hook the game up to it, but all my tests are working. I can add high scores to the database and I can retrieve them in a few different ways. Today I’ll be starting to work on the game-side implementation, which will probably be more work than the server-side. I have to make a few UI changes in the game to support local vs. global high scores and handle all the error cases around connecting to the server. I’m hoping to have something I can send out to testers by mid-late next week.
It feels good to get back to coding again. There are a few other things I want to put into the 1.2 update as well. I’m hoping to submit to Apple by the end of the month. After that, I’ll actually be able to start working on my next project. Shocking!
Have a good (long) weekend everyone!
Owen
Toronto iPhone Dev Meetup – Tonight!
Wednesday, May 13th, 2009
That’s right, the Toronto iPhone Developer Meetup is happening tonight! Once again, here are the full details:
Date & Time:
Wednesday, May 13, 2009 – 7:00pm
Please note: The time is earlier tonight than last time to accommodate some presentations.
Place:
FITC / Rich Media Institute
156 Augusta Ave (Kensington Market area)
Toronto, ON
MAP
Following the presentations we’ll head just North to a bar called The Embassy Bar (223 Augusta Ave).
Who can attend?:
Anyone currently working or interested in working on iPhone development can attend. If you’ve got an App available, show it off. If you’re working on an App, ask for some feedback.
We have two presentations lined up for tonight:
Presentation: Box2D Physics Engine
Name: Luke Lutman
Compay: zinc Roe Design
Job Title: Lead Designer / Lead Programmer
Website: http://www.zincroe.com
Presentation: App Store Rules you Should Break
Name: Jason Moore:
Company: xinsight
Job Title: Developer
Website: http://www.bikefixfinder.com/
If you’re on Facebook, join our Facebook Group which has a link to the Facebook event for tonight.
Hope to see you there!
Owen





