Saturday, April 18, 2009
Introducing Inspire Me!
Based on inspirational boards used by photographers and dreamers alike, Inspire Me allows users to create dynamically generated collages from their photo albums. Support for panning, zooming, and saving them to an album to email to friends is included in 1.0. The next version will randomly size the photos, too, and provide the option of background color as well. Look forward to it on an App Store nearest you any day now. :)
Thursday, March 5, 2009
Kanji Sensi submitted!
The spiral translations I had in mind for my Kanji Sensi app are too processor-intensive to complete timely on the iPhone's hardware. With 200 points to compare within a character against the points that comprise the path of a user's strokes, I'm limited to about 8 translations per stroke. This is about 100,000 iterations (character points times path points). Any more and the app lags between strokes. To make the most of these 8 translations, I assume that the user will most likely draw above or below the character and make 4 translations spaced 50px apart above and below. There's not much room to be drawing on the side or diagonally. There will be minor frustration on depending on how close a user draws to each 50px offset but its the best that can be done with the iPhone's limited resources.
With that said, I am proud to announce the completion of version 1.0 of Kanji Sensei. Future versions will have more characters (currently 128) and more accurate shape comparison. Let me know what you want to see and I'll work it into the future release. :)
With that said, I am proud to announce the completion of version 1.0 of Kanji Sensei. Future versions will have more characters (currently 128) and more accurate shape comparison. Let me know what you want to see and I'll work it into the future release. :)
Wednesday, February 25, 2009
Variable-length array of primitives in Objective-C
You won't always know the size you need to allocate for an array at compile time and using any more memory than necessary by allocating more than you'll ever need is out of the question for an embedded system. If only we had the same kind of constructs that are available in C++ or we were working with a superset of C... oh right - we are! The Foundation library provides an NSMutableArray class but it only works with objects. No worry, just wrap your primitive(s) with a custom class that inherits from NSObject and you're set. :) Of course there is some overhead to working with objects but not nearly as much as allocating an exorbitant amount of array indices.
Monday, February 23, 2009
Shape comparison algorithm
Here's a simple algorithm for comparing shapes when resources are limited such as on the iPhone. Basically, you want to pre-generate points that lie within and just outside of your shape in the language of your choice and then save them as serialized data in a property list file. Property lists are formatted as follows:
name
base64encodeddatawithnolinebreaks
It's important that your base-64 encoded data does not have line breaks in it. The Java class I found for base-64 encoding did this and I had to modify it not to. The data will load in successfully on the iPhone but at the line breaks it seems the data starts to not match. Sometimes it was off by 4 bits, but I couldn't find a consistent pattern to offset it the other way. Using data elements is much more efficient than storing coordinates in their own elements. Property lists may not load at all if they get too big. I'm guessing due to memory restrictions.
Once you have the points loaded on the iPhone platform, you can compare these points to the points of other shapes (perhaps ones drawn by finger?) by measuring the distance (I'm sure you remember this formula from math class?). It's up to you to determine the threshold necessary for your application. Keep the number of points less than in the thousands so that the phone's processor isn't tolled. If comparing against an inaccurate human-drawn shape, you may want to spiral the shape's points around until you maximize accuracy to give the user the best chance at matching the shape.
base64encodeddatawithnolinebreaks
It's important that your base-64 encoded data does not have line breaks in it. The Java class I found for base-64 encoding did this and I had to modify it not to. The data will load in successfully on the iPhone but at the line breaks it seems the data starts to not match. Sometimes it was off by 4 bits, but I couldn't find a consistent pattern to offset it the other way. Using data elements is much more efficient than storing coordinates in their own elements. Property lists may not load at all if they get too big. I'm guessing due to memory restrictions.
Once you have the points loaded on the iPhone platform, you can compare these points to the points of other shapes (perhaps ones drawn by finger?) by measuring the distance (I'm sure you remember this formula from math class?). It's up to you to determine the threshold necessary for your application. Keep the number of points less than in the thousands so that the phone's processor isn't tolled. If comparing against an inaccurate human-drawn shape, you may want to spiral the shape's points around until you maximize accuracy to give the user the best chance at matching the shape.
Sunday, February 22, 2009
Using timers on the iPhone
The iPhone's threading model is based on run loops. One way to execute code asynchronously is to add a timer to a run loop and put the asynchronous code in the selector given to the timer constructor:
[[NSRunLoop currentRunLoop] addTimer:[NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerFired:) userInfo:nil repeats:NO] forMode:NSDefaultRunLoopMode];
return character;
}
- (void)timerFired:(NSTimer *)timer {
ready = YES;
[self setNeedsDisplay];
}
It's just that easy. This is part of Core Foundation so no extra frameworks are needed. :) If it's not intuitive, the repeats parameter decides if it will run only once. In this case, I've used a timer to clear a graphics context after an interval which was used as a hint before the user has to draw a character on the screen.
[[NSRunLoop currentRunLoop] addTimer:[NSTimer timerWithTimeInterval:3 target:self selector:@selector(timerFired:) userInfo:nil repeats:NO] forMode:NSDefaultRunLoopMode];
return character;
}
- (void)timerFired:(NSTimer *)timer {
ready = YES;
[self setNeedsDisplay];
}
It's just that easy. This is part of Core Foundation so no extra frameworks are needed. :) If it's not intuitive, the repeats parameter decides if it will run only once. In this case, I've used a timer to clear a graphics context after an interval which was used as a hint before the user has to draw a character on the screen.
iPhone Development Tips
Tips presented at BarCamp Miami 2009:
XCode:
XCode:
- Identifier definitions can be tracked down by command-double-clicking them, providing a drop-down menu for ambiguities.
- Code completion exists if you type slow enough if you have the proper header files included.
- Command+[ or ] tab shifts code rather than the tab key.
- If a property lists doesn't want to load in to a dictionary, keep in mind that there is a little known limit to its file size, which I believe to be around a megabyte. I ran in to this when working on my latest app that stores a lot of coordinates for different characters.
- Retain variables when you want to dereference them in another scope (fatal runtime error otherwise, EXC_BAD_MEMORY i believe).
- Retain can be avoided by using factory methods or making the variable a class property although that makes it public (you'll still need to release it).
- Release variables when you're no longer going to use them (typically in dealloc:).
- AVAudioplayer (2.2+ only) allows for simple audio playback, but doesn't support streaming or low-level audio manipulation (see Audio Queue Services).
- A limitation I found in the Image View was that image file size or resolution can't be too big or else it may not show up at all.
- Drawing context only available in drawRect: even if you get a context object back from UIGraphicsGetCurrentContext().
- Set up a "state" in a fashion appropriate for your application (maintain an array of paths for simple doodle app to iterate through and add to context during drawRect:).L has lost some ground to DirectX, but this mobile subset of OpenGL seems to have found a niche. Development for OpenGL is an entire topic in itself but if you're new to it and you have a game in mind, I'd like to recommend some open source engines that have been written for OpenGL: cocos2d, oolong, oc3d, sio2, and nebula3. It's exciting to see what the open source community is capable of achieving once Apple removed the NDA for developers. If you're interested in game development or an immersive application, I can also recommend for CC search, freesound.org, and flashkit.com for free sound effects and images.
- cocos2d
- oolong
- oc3d
- sio2
- nebula3
- ccsearch
- freesound
- flashkit
- Buy developer program ($99)
- Create identity certificate signing request
- Submit to Apple for an identity certificate to install
- Add device to account
- Create mobile provisioning profile (links identity to device)
- Install into XCode and choose profile from Build settings
- If you get a device error in the Organizer window, follow the error message and restart the device!
- Code sign with distribution profile
- ZIP app up as a filename with no spaces
- Set release date > 1 week in the future (App Store sorted by release date and will take at least a week to be approved)
- Prepare an icon, screenshot, description, and website (as simple as a blog)
- Extensively test app to avoid missing release date! Resubmissions take at least a week, too.
- Do web views show a meaningful error message when there's no connection?
- Is the app intuitive and usable?
- (Rumored) Does it compete with iTunes?
BarCamp Miami 2009
I'll be presenting iPhone development tips if I can get a time slot today at BarCamp in Miami! After my presentation, I'll tweet out a link to this blog and make an update by tomorrow with my presentation notes. I hope to inspire others to make some great apps by quelling any fears about the development or deployment process.
Subscribe to:
Posts (Atom)