iOS development highlights: August 2010
Here are some of the things from across the iOS blogosphere I found interesting this past month. I hope to return from my summer blogging hiatus soon.
- In my opinion, the hottest topic in August was the automation of distributing beta builds of iOS apps to beta testers. In the wake of the improvements Apple made to the process in iOS 4.0 and Jeffrey Sambells’s excellent June post on iOS Wireless App Distribution, several frameworks/apps popped up to automate this process:
- iOS Beta Builder by Hunter.
- Testflight by Neven Mrgan.
- Hockey by Buzzworks.
- Pierre Lebeaupin wrote A few things iOS developers ought to know about the ARM architecture already in July, but I only read it in August. Even if most developers do not have to interact directly with the CPU, it never hurts to know a little bit about what’s going on under the hood. Especially on less powerful devices like the iPhone.
- Vincent Gable shared a very useful macro to log the contents of variables regardless of their type. It can save you a lot of time during debugging. No wonder Vincent calls it “the most useful Objective-C code I’ve ever written”.
- Finger Tools, an interesting UI concept for the iPad that gets rid of the common toolbox/toolbar/palette in canvas-oriented apps. I am not convinced that this will actually work well in a real app but it is an innovative idea.
- Prototyping: You’re (Probably) Doing It Wrong by Noel Llopis. Focused on game development but useful for productivity apps, too.
- Jeff Kreeftmeijer asks, Why aren’t you using git-flow? git-flow is Vincent Driessen’s cool Git branching model cast in an easy-to-use Git extension.
iOS development highlights: July 2010
Unlike myself, the iOS developer community has been quite active posting great content this month. Here are some of the things I found most interesting from across the blogosphere:
- Back in June, John Siracusa talked about the possiblity of Apple replacing Objective-C with a new platform based on an abstracted memory model. In a series of posts (Surpass, Not Replaced, Objective Dash) Jesper explored a similar path, and finally Matt Gallagher chimed in: Is a virtual machine for Cocoa programming inevitable? All of these posts are very interesting reads. I certainly hope that Apple is working on leaving Objective-C’s C legacy behind.
- Martin Pilkington about new features in the Objective-C runtime (called “Objective-C 2.2″ by Martin). Say goodbye to
@synthesize! - Terminal Tips and Tricks For Mac OS X is a super-useful collection of tricks that recently made its way around Twitter. My favorites are opensnoop and mdfind -live (via Christian Beer).
- ShareKit is an open-source library that enables your iOS app to share content on Twitter, Facebook, etc. with just a few lines of code.
- Seriously is a new HTTP library with an easy-to-use block-based interface (via Joost Schuur).
- It never hurts to have another pull-to-refresh implementation (made famous by Tweetie 2) so Leah Culver has written one.
- The ever-resourceful Matt Gemmell developed the
UISplitViewControllerApple should have made: MGSplitViewController can display the split view in landscape and portrait, has a vertical and a horizontal layout, and interactive sizing of the master and detail panes.
WWDC 2010 videos already available. And free!
Apple has already posted the videos recorded at WWDC last week. And what’s even more incredible: they are downloadable for free at http://developer.apple.com/videos/wwdc/2010/ for registered Apple developers! Last year’s videos were only free for WWDC attendees and were priced $299 (iPhone sessions only) or $499 (iPhone and Mac sessions) for the rest of us. And even at that price they were worth it. If you are serious about iOS development, do yourself a favor and watch as much of these 100 hours of material as possible. You are guaranteed to learn a lot.
PS: Keep in mind that the contents of the videos are still confidential, just as they were for WWDC attendees. Apple will not be amused if we share any non-public information we learn from the sessions.
App Store-safe Page Curl animations
Even if its usefulness is questionable, the page curl has become one of the signature effects of Apple’s iOS devices so it is no surprise that many developers would like to implement this effect in their apps.

iBooks on the iPad doing a page curl
Apple uses private APIs
The problem is that the page curl animation used by Apple is not exposed in a public and documented API. Steven Troughton-Smith did a great job at documenting how Apple’s implementation works in his post Apple’s iBooks Dynamic Page Curl. Although Steven’s sample code is a bit rough (as Steven himself admits), the inner workings become clear: Apple has written a custom Core Image filter that is accessible with the undocumented kCAFilterPageCurl constant. (Yeah I know, Apple actually tells us in the documentation that “Core Image is not available in iPhone OS”. They lied.)
This filter accepts to input values, inputAngle and inputTime, to control the angle from which the layer is curled up and the magnitude of the curl. For a page curl animation, we would animate inputTime from 0.0f to 1.0f. To attach the filter to a layer, simply add it to an array and assign the array to the layer’s filters property (ignoring that the documentation says this leads to undefined behavior. In this case, undefined behavior is exactly what we want.).
From Steven’s code (edited for clarity):
@class CAFilter; extern NSString *kCAFilterPageCurl; // From QuartzCore.framework static CAFilter *filter = nil; ... // In -touchesMoved: filter = [[CAFilter filterWithType:kCAFilterPageCurl] retain]; [filter setDefaults]; [filter setValue:[NSNumber numberWithFloat:((NSUInteger)fingerDelta)/100.0] forKey:@"inputTime"]; CGFloat _angleRad = angleBetweenCGPoints(currentPos, lastPos); [filter setValue:[NSNumber numberWithFloat:_angleRad] forKey:@"inputAngle"]; pageView.layer.filters = [NSArray arrayWithObject:filter];
The App Store-safe way
I hope Apple makes this public in the future (and if you want to have it, too, you should file a bug and request it). In the meantime, Tom Brow has written Leaves, a simple component that achieves a page curl effect through a very smart combination of mirrored and shaded layers (for translucent pages) and gradient layers (for shadows). Basically, Tom adds to the layer that contains the page content (topPage):
- an overlay to shade the page during the curl animation (
topPageOverlay), - a gradient layer that acts as the top page’s shadow during the curl (
topPageShadow), - a mirrored image of the page that will be displayed on the back of the topPage layer during the curl (
topPageReverseImage), - a nearly-white overlay to soften the
topPageReverseImage, - and the page below the current page that will become the new
topPageafter the curl has finished.
The end result is not quite as stunning as Apple’s solution but it is a very good workaround.
As I played around with Tom’s code (I encourage you to take a look at it, it is very clean), I noticed that LeavesView did not support displaying two pages side by side in landscape mode, so I modified Tom’s code accordingly. At first, I planned to duplicate the entire layer hierarchy for the second page, but then I noticed that even in the side-by-side view it is enough if only the page on the right is animated. It was enough to add a leftPage layer, modify the page skipping algorithm (skip two pages instead of one) and the display of the topPageReverseImage layer (display an image of the next page instead a mirrored image of the current page). This is what you get:

Page curl in the Leaves project in side-by-side view
The code is not yet perfect: the topPageShadow is not aligned correctly and I struggled a bit with Tom’s implementation of the page image cache so the code in that section is quite rough. Tom has not yet integrated my modifications into his repository but you can already check out my twopages branch (I love GitHub!). When there is time, I hope we can improve it even more.
Update June 21, 2010: John from maniacdev.com made a nice screencast of the effect in action. Thanks!
UIWebView’s weird PDF display bug on the iPad
UIWebView seems to have a weird display bug connected to PDFs and interface rotation in iPhone SDK 3.2. This is how a PDF displayed in a UIWebView looks on the iPad after you rotate the device from portrait to landscape:
The PDF appears to be split in half vertically along an edge that was right in the middle of the page while the device was in portrait orientation. The right half is vertically offset from the left half. Other people have also noticed it so I believe it is a genuine bug.
To reproduce it, try the following:
- Create a UIWebView and set
scalesPageToFit = YES. - Embed the web view in a view controller that supports both portrait and landscape orientation.
- Load a PDF file into the web view.
- Rotate the iPad from portrait to landscape or vice versa.
Or download the sample project I have created.
I can reproduce this consistently with a number of different PDF files using iPhone SDK 3.2 both in the iPad Simulator and on an actual iPad. The bug does not appear with HTML content nor is it present on the iPhone. It also disappears if you zoom into the page just a little bit or if you set scalesPageToFit = NO.
Workaround: Reload the document after rotation
The only workaround I have found so far is to reload the document after the device has been rotated. It is not very pretty because reloading can take some time and the user can still see the buggy display for a second, but other than that it works. The best place for the reloading code seems to be your view controller’s -didRotateFromInterfaceOrientation: method.
Reported to Apple as Radar #8065859.
Update June 12, 2010: Apple has confirmed this bug as a duplicate to #7790957.
World Cup 2010 Tracker Spreadsheet
Update June 25, 2010: Now that the group stage is over I have updated the spreadsheet with the results of all the group stage games. If you download it now, you can dive right into the knockout stage.
Update June 7, 2010: There is a bug in the first version of the spreadsheet that results in a wrong team being selected for the seventh game in the Round of 16. Thanks to @galdo for pointing it out. The download link below points to a fixed version.
I haven’t had the need to use a spreadsheet since I quit my job a few years ago, but after getting the iPad I wanted to try out Numbers and so I built a spreadsheet for tracking the 2010 World Cup yesterday. Inspired by Fraser Speirs, who published his World Cup Tracker Spreadsheet last week. Since Fraser’s version requires a little bit of manual effort (it doesn’t automatically determine the winners of the group stage), I thought I could do better and make it fully automatic. I hope you like it:
Download: World Cup 2010 Spreadsheet for Numbers (1.4 MB)
All you need to do is enter the scores for each on the fixtures sheets (one sheet per group) and, later, on the Knockout Stage sheet. The trickiest part of automating the calculation of the group rankings are the complicated tie-breaking criteria. To rank the teams, the spreadsheet considers the number of points, the goal difference, and the number of goals scored. If two or more teams are still tied on these criteria, the calculation will break. Let’s just hope that won’t happen. (FIFA then considers the match(es) between the teams to break the tie.)
(Beware: I haven’t tested the spreadsheet very thoroughly so there might well be some bugs in the formulas. If you find one, please tell me and I’ll fix it.)
Thoughts on Numbers on the iPad
We already know that the iPad is far more than a consumption-only device and that it has a lot of potential for content creation, as well. That said, it took me a lot longer to build this spreadsheet on the iPad than it would have with Excel or Numbers on a “real” computer. I spent about 4 hours to make this yesterday and I estimate that I could have gotten the same result in about 1 hour with a desktop app. I think the main reasons for this discrepancy are:
- The iPad’s smaller screen makes it harder to navigate and formatting your content takes more time as you always have to switch back and forth between your content and the inspector.
- The touch interface is just not as well suited to a spreadsheet app as mouse and keyboard (with powerful keyboard shortcuts) are.
- As amazing as it is how much functionality Apple managed to put into Numbers on the iPad, it does lack some key functionality (to me), namely multiple selections and the ability to move content between tables without breaking the references (dragging between tables does not work and cutting-and-pasting breaks the references).
How to debug an app that was launched by Push Notification or URL handler
I’ve been fairly active on Stack Overflow lately. To date, I have answered 315 questions there and while I haven’t asked any questions myself, I have profited immensely from the knowledge others have shared there. It is truly a great site, so much better than most programming forums. I think many questions that I have answered might also be interesting to you and so I thought I’d share some of the more interesting ones (and the answers, of course) here, perhaps with a little more detail than on SO.
Let’s start with this one: How can I debug an app that was started by an external event such as a push notification or a URL handler? You don’t click on Build and Debug in these cases, so how do we get the debugger to notice? You have two options here:
1. Use NSLog statements and inspect them in Console.app
The output of your NSLog() calls not only show up in the Debugger Console in Xcode but also in the system logs. To look up the logs for the simulator (useful for testing a custom URL scheme), open Console.app in OS X, select Console Messages in the left pane and then search for the name of your app in the Filter field. To see the Console messages on the device (e.g. to test how your app handles an incoming push notification), open the Organizer in Xcode, select your device and switch to the Console app before your app gets launched.
2. Ask the debugger to wait for your app to launch
Sometimes, NSLog() is just not enough and you want the full power of the debugger. No problem:
- Set a breakpoint where you want it e.g. in
application:didFinishLaunchingWithOptions:. - Select Project > Edit Active Executable. On the Debugging tab, select the “Wait for next launch/push notification” checkbox:

- Build and Debug as you normally would. The Console will show you a message that the debugger is waiting for your app to launch.

- Launch your app by invoking your custom URL or sending a push notification. The debugger will automatically attach to your app’s process and stop at the breakpoint.
iPhone SDK Beta to Beta API Diffs
Apple released a new beta version of the iPhone SDK today. So what changed from the last beta, you ask? It’s a little hard to tell from the links Apple provides on their developer website because the link to the API diffs (iPhone developer account required) always lists all changes from the most recent stable version. So if you have already downloaded beta 1 and beta 2, you are now reading the same document for the third time. Thankfully, Apple also provides a documents that only lists the changes from the last beta version, but it is not listed on the developer home page:
https://developer.apple.com/iphone/prerelease/library/releasenotes/General/iPhoneSeedAPIDiffs/index.html (iPhone developer account required)
This URL seems to remain constant between beta releases. In other words, it always lists the differences between the most recent beta release and its predecessor. If you follow the SDK betas it’s a good idea to bookmark that page.
Set the zoom level of MKMapView
A very nice MKMapView category by Troy Brant that allows you to zoom the map by settting the zoom level (as in the Javascript Google Maps API) in addition to Apple’s way of zooming by modifying the map’s region:
Unfortunately, MapKit on the iPhone does not include a way to set the zoom level. Instead, the zoom level is set implicitly by defining the
MKCoordinateRegionof the map’s viewport. When initializing the region, you specify the amount of distance the map displays in the horizontal and vertical directions. The zoom level is set implicitly based on these distance values.Instead of dealing with this region business, I wrote a category that adds support for setting the zoom level of an
MKMapViewexplicitly.
Troy also wrote an extensively detailed post on the mathematical background of his code. Great stuff!
I’m available for contract work
As of now, I am available for contract work developing iPhone and/or iPad apps. If you are looking for an experienced developer who already published an iPad app and a very successful iPhone app (Songtext was the top paid app on the Germany App Store), please e-mail me at ole@oleb.net. I look forward to discussing your projects with you. I am based in Berlin but working remotely or travelling would be no problem.
Ich bin ab sofort auch für Freelance-Aufträge als iPhone- und iPad-Entwickler verfügbar. Wenn Sie einen erfahrenen Entwickler suchen, der bereits eine iPad-App und eine sehr erfolgreiche iPhone-App (Songtext war für einige Zeit die Nr. 1 im deutschen App Store) veröffentlicht hat, kontaktieren Sie mich bitte unter ole@oleb.net. Ich wohne in Berlin, bin aber auch für auswärtige Projekte offen.



