Maintaining iPhone Compatibility

I recently decided to add iAds to PhotoTangler Lite, in exchange for removing some of the limitations. One of the problems that arose is that iAds aren’t available on older versions of iOS. Since the beginning I’ve been trying my best to make sure my app runs on every iPhone out there, including the very first Edge network devices. The steps I ended up taking were as follows:

  • Set the iOS deployment target low (iOS 3.1 in my case)
  • Add the iAd framework to Build Settings, but flip from Required to Optional
  • At runtime, detect the iOS version using [[UIDevice currentDevice] systemVersion]
  • If it’s a high enough version, enable ads and reduce limitations.
  • If ads aren’t supported, keep previous Lite version limitations.
  • I tested it in all the simulator versions, an old Edge iPhone, a 3GS and an iPhone 4. Worked perfectly on all of them for me. If you’ve got a similar challenge with your own apps, this approach might be worth a shot.

    PS – One extra tidbit: [[[UIDevice currentDevice] systemVersion] floatValue] can be used to get the version number as a float.


     

    Backwards iPhone Development

    PhotoTangler was my first iPhone app. My programming background has largely been in 3d video games and simulation, primarily on the Windows platform. I’ve been using a variety of other platforms for quite a while (including Linux and Mac), but most of my serious development projects had been on the Windows side. To learn about iOS development, I spent a week consuming two iPhone books (and Apple’s documentation), then got to work on my app idea.

    When I began the project, I had to make a few decisions about what versions of iOS to support. For example if I used OpenGL ES 2.x, my app would only work on the iPhone 3GS or later. It so happened I had one of the very first iPhones (Edge, 4GB) lying around, so I decided to test its capabilities. After a quick prototype, I concluded that ES 1.x could do all i needed, meaning I could support any iPhone out there. My strategy was then to do all development on this ancient phone, expecting that if it ran well on this bad boy, it’d run like a dream on newer phones. This is something I used to do in games– write stuff on older machines, with older graphics cards– with hopes it’d run well on the newer stuff. And it usually worked great. Turns out that for the iPhone, that just wasn’t the case.

    I wrote and tested the app on the aforementioned phone, as well as an iPhone 3G that a friend gave me. By the time it was finished, everything worked perfectly. I hammered it with a pretty rigorous combination of test runs each time I did a build, and it never crashed. It seemed rock solid. I sent it to a handful of friends for testing, and they reported good things. So I published it.

    For the most part, I considered the launch a success. People seemed able to run it, and it was selling better than I expected. But I kept receiving sporadic reports (or the occasional negative review) about the app crashing. I followed up with anyone I could, trying to get the steps to reproduce it, but I simply could not get it to crash on my old iPhones… ever! The whole time I kept thinking “if it runs on this old thing, it should run on anything!”

    The turning point came when something strange happened with the App store. I pushed a new version (1.1) of the app to Apple for review, and the full version was accepted– but the Lite version was rejected due to crashing. This was odd because they were the exact same code with a few #defines to limit the number of images the Lite version can import. I had to figure it out. The crash report they sent was from an iPhone 4, matching my growing suspicion that crashes were only happening on the newer phones. I bit the bullet and bought an iPhone 4, hoping I could find a way to reproduce the crash (after playing all the latest 3d games of course!) Turns out, I could. First try.

    As most developers know, being able to reproduce bugs is typically the hard part. Once I was able to, fixing them was simple. But crashes aside, I was kind of shocked at how many differences I noticed in the way my app looked and ran on the iPhone 4 compared to my other phones. It took barely an afternoon to fix all of the issues I found. Most were related to what happened when memory warnings occurred if a lot of apps were open simultaneously, which explains why it didn’t crash for all iPhone 4 users. Since 1.2 of the app was released, I haven’t received a single crash report. Knock on wood!

    Overall, I suppose I’d expected a greater degree of backwards compatibility as I’d been used to with most other SDKs I’ve used. I learned the hard way that deprecated on iOS really means deprecated. Of course I take full responsibility for the quirks that were in my code. But I wrote all this both to remind myself, and to caution others (with limited access to devices) against using a similar development strategy. Expecting an older baseline to provide maximum compatibility didn’t work well for me, though I also don’t know that it would’ve worked any better the other way around. Moral of the story? Assume nothing. Test everywhere. Best of luck.


     

    Making of an iPhone Promo Video

    If you’re an app developer, one of the best ways to get people to look at your app is to make a short, sweet promotional video that shows off the core features. For apps that do somewhat unique things (such as PhotoTangler), it can be very difficult to describe in words what the app is, let alone why someone should spend their precious time giving it a try. Ideally a video will solve that! In this post I quickly explain the steps I took to create the following promo video:

    For starters, the core problem was finding an approach to record video of my app, which could then be cut and edited into a nice promo video. To my knowledge, there’s no reasonable way to export video directly from the iPhone, which left the following primary options: a) Run the app in the simulator, or b) Film the phone with a digital camera.

    Given the number of shoddy cam videos I’ve seen for apps (and the fact that I don’t have a good camera), I decided to explore the use of the simulator. The goal was to run the app directly in the simulator, and record video using a desktop capture application. A bit of Google searching revealed a variety of desktop capture apps, at myriad price points. However when I asked my Mac developer friends, consistently the most popular recommendation I received was for Snapz Pro X (no affiliation), which I found to be simple and effective.

    Equipped with fancy capture software, the next obstacle was figuring out how to record the actual demo. For apps with simple inputs, recording from the simulator is smooth sailing. In my case however, I needed to use multi-touch to effectively show the features. That’s of course a bit of a problem with a single mouse! That is, until I found out about iSimulate (again, no affiliation.)

    iSimulate is a slick app (and corresponding SDK) which lets you use your actual iPhone device to control your app through the simulator. The quick version is that you link with their provided sdk library, then run your app in the simulator. It creates a listen server, which you can connect to from your phone (via Wi-Fi) using the iSimulate app on the device itself. It forwards touch events, accelerometer data, etc, to your app transparently. It can also stream video back to the phone so you can see your app on the device as well. It might sound pretty complicated, but the cool thing is that at least in my experience with it, it just works. There’s a free trial version.

    Once I had a way to capture video and device inputs, the rest was a piece of cake. I scripted out a simple sequence of events to show off the main features in under 2 minutes, and quickly edited the pieces together in iMovie. The music I used came from Kevin MacLeod’s Royalty Free Music collection, which has a bunch of great content under the Creative Commons attribution license.

    The entire process took under 2 hours, and I’m pretty happy with the results. Hopefully the above explanation gave you some ideas about how to get your own video made. And if you know of any better ways to capture iPhone video or input, I’d love to hear about them.


     

    Writing an HSV Color Picker

    Over the weekend I got to the point in one of my iPhone apps where I needed to add a color picker. I quickly discovered there isn’t a standard color picker control for iOS, so I figured I’d write my own.

    Color pickers come in all shapes and sizes, depending on platform, UI toolkit, etc. One of my personal favorites is the HSV color wheel, where hue changes by angle, saturation by radius, and the value parameter is edited separately (typically with a slider.)

    The basic algorithm to generate the color wheel above went like this in my implementation:

    for (y pixels to span -half_height to half_height)
    {
        for (x pixels to span -half_width to half_width)
        {
            // atan2 returns the angle from -pi to pi
            // radians so we convert to degrees here.
            angle = atan2(cy, cx) * 180 / pi;
    
            if (cy < 0)
            {
                angle += 360;
            }
    
            // calculate the current distance from center.
            distance = sqrt( (cx * cx) + (cy * cy) );
    
            // calculate the percent of the 'maximum radius' this is.
            // max_radius is the lesser value of half_width, half_height.
            saturation = distance / max_radius.
    
            // we can now simply convert from HSV to RGB.
            color at cx, cy = hsv_to_rgb(angle, saturation, value);  
        }
    }
    

    The 'value' parameter, specified separately, would just be passed in.

    The only missing step above is the conversion from HSV to RGB. For that part, I used the algorithm described in the classic reference book, Computer Graphics: Principles and Practice, which essentially breaks the circle into 6 sections of 60 degrees to interpolate the colors in each accordingly. You can find sample implementations here (via Google Books), or here.

    Once I got that part implemented, the rest was pretty straight-forward. When the user taps anywhere on the circle, the hue/saturation combination is shown in a preview box, indicating the selected color. Separately, they can touch the 'value' gradient to manipulate the "brightness." I implemented all of the visuals in custom drawRect code after subclassing UIView. I've been playing with overlaying some image 'skins' to make it look a little more robust, but the basic functionality works pretty well.


    Download on iTunes Android app on Google Play