Pull To Activate design
Not wanting to create a ‘run of the mill’ alarm app, I opted to use a ‘pull to activate’ design over a traditional ‘set alarm’ button. This kind of design is more commonly seen within Apples mail app (though thought to have been pinched from Loren Brichters original implementation within Tweetie). The pull to activate in my implementation uses a scroll view (as opposed to the traditional UITableView), all other views are then placed as subviews of the scroll view. Once thing you’ll find when you do this is that your scrollview looses it’s ability to scroll. This is due to auto-layout constraints that are automatically applied when using Auto-layout. Apple has a technical note for dealing with this ‘special case’ which can be found here
Unfortunately , whilst one of the work-arounds suggested did the trick when running on the iPhone 5, it didn’t work on the smaller screen size of the iPhone 4 and 4S, it was a matter of choosing between one or the other, which I wasn’t prepared to do. Therefore I built the app without auto-layout, which required much more work to get everything positioned correctly on both screen sizes across the whole app, but meant I was able to keep the ‘pull to activate’ design.
That was problem one solved, the second problem cropped up when it came to knowing when to presenting the modal alarm view controller after pulling down to activate the alarm. At first I set up an NSTimer for a pre-determined amount of time, which when fired, presented the modal alarm view controller showing the remaining distance to the destination. The problem was that the location manager hadn’t always got a fix on the users location or done the calculations to obtain the distance, when the alarm view controller was presented and so all this information appeared blank for a few seconds until it was updated. If the location manager was never able to get a location an error message was presented and it would be up to the user to deactivate the alarm and try again. This was obviously not ideal.
To solve this I used the delegation design principle. When the user pulls to activate the alarm, a request is sent to the location manager class which attempts to obtain the users current location, only when it has this location and has done the necessary distance calculations, does it ‘call back’ to it’s delegates ‘didUpdateLocation’ method, in this case the delegate being the Home or Recent’s view controller. I still set a timer up at this point for 20 seconds in case the location manager isn’t able to obtain a fix, so that the app can ‘timeout’, end the location manager and alert the user. Note that the main thread is not blocked at any point during this process.
Although the ‘pull to activate’ principle was much more work to implement than say a button, I feel it really add’s to the overall usability of app.