Updating for Modern iOS Design – A Case Study

TL;DR — Check out the pictures and videos on this page, and you’ll see how I adapted the basic circular menu of Click version 1 to fit the new iOS 7 design aesthetic, not just in visual terms, but also in interaction style: clean and almost chrome free, with more color, more seamless transitions, new inertial/physics-y interactions and direct manipulation transitions.

 

Hello Again!

As you can probably imagine, a LOT has happened in my life in the last almost two years since I’ve posted on this blog (and therefore also on iDevBlogADay)! And most of it has not been iOS development related, so I guess that’s my excuse for such an incredibly long time between posts. But, I have been working when I have the time, and I just released a new version of my iPhone app called Click Metronome. The original version was the topic of many of my posts here on this blog, especially about the design of the circular control. For this post, I thought it might be interesting to explore some of the design changes I made to Click when releasing version 2. The principles behind the design – and the features of the app – are largely the same, but the actual look and feel is completely different. So first, how about a look at a screenshot from version 1, and then the promo video for the new version for iOS 7+. Can you guess which is which?🙂

 

Screenshot 2014.08.02 13.38.42

 

Circular Menu

At the time, I was really happy with how Click turned out. Then – and now – there’s a lot of metronome apps out there, but they seem to either be too simple and missing key features, or feature-rich but with a screen that’s completely full of buttons. So, one of my main goals for Click was to offer all the main features people would want – wide tempo range, variety of time signatures, accent options, etc. – and make them quickly accessible, but without cluttering up the screen with tons and tons of buttons. So, after much iteration, I came up with this menu system that showed all the current settings around a small circle. Then, the user taps an item and all the options for that setting are revealed in the circle, ready to be set by rotating. Here’s that menu in action in version 1 and version 2 (watch in slo-mo):

 

Click1MenuSmall

Click2MenuTapSmall

 

Version 1 Problems and Fixes:

I felt like I accomplished the goals I had set out, and watching people as they used the app, they always eventually figured out how to use it. But, it was never as intuitive and easy as I had hoped. As I got feedback from others, and as I thought more and more about the app myself, I came up with a whole list of problems with the implementation of the menu:

Continue reading

Circular Scrolling + Inertia

Why Inertia?

I’ve talked a lot on this blog about the circular scroll-view/table-view thing I created for my metronome app, and while I’m very pleased with how the whole thing turned out, I was still annoyed that I hadn’t figured out how to do one thing: give it inertia like UIScrollView. A commenter on one of the posts even asked me about inertia, and I basically just flat out said I’d like to, but it would be too hard! But after that, it just kept bugging me; there had to be a way. Inertial scrolling on iOS – and now on OS X too – just feels so nice. It’s one of those things that many people probably don’t even think about or notice until it’s gone. After feeling the smooth scrolling and realistic deceleration of UIScrollViews, my little rotary control just feels like garbage. I mean, come on, you give it a little flick and it stops rotating immediately when you lift your finger!? Lame! Frankly, my control just doesn’t feel quite completely at home on iOS yet, and I want to change that.

Maybe UIScrollView Can Help!

I got really exciting after watching the WWDC 2012 video for Session 223: Enhancing User Experience with Scroll Views. In the presentation, they give an excellent demo of how to leverage the physics of UIScrollView even when your app uses OpenGL. The UIScrollView is not used for any drawing, but by passing touches through it, listening for the scrollViewDidScroll, and reading the contentOffset, you can enjoy all the benefits of UIScrollView like inertia and edge bounce without actually drawing your content in the scroll view itself. Maybe, I thought, I can use that same trick on my circular scroller. Using the same techniques from the video, I was able to get up and running with the same circular action as well as a bit of UIScrollView provided inertia, but it just did not feel right at all. The geometry of linear scrolling and deceleration just don’t line up with what I need in terms of angular rotation.

Eureka!

The video technique didn’t work out quite like I had hoped, but I still took away one key idea: implement the inertia in the touch handler, not in the circular view itself. Seeing as how no one has seen the details of my implementation, that might not make sense to anyone but me right now, but I’ll try to explain. At its most basic, my control has two parts: the transparent view which interprets the touches as circular movements (a gesture recognizer, if you will, although it’s not an actual UIGestureRecognizer subclass) and the display view that receives notifications of those movements and rotates, swapping elements in and out sort of like UITableView cells. I had already implemented a bit of animation in the view component that allowed it to center on a certain cell, and I kept trying to think how I could make this also work with a longer rotation, and I was running into a lot of problems with the cell swapping during the rotation animation. But, if I implement the inertia on the control side and use the same delegate call for rotation that comes from an actual touch OR from the inertia, the view side doesn’t even know the difference. And it actually worked pretty well without much modification at all!

Check out the Repo

So, here’s the real/final point of this post: I’d love to get this whole rotation control thing (or most of it, at least) out into the wild as an open source component, but it’s been hard finding the time. It’s a fairly complex API, and I don’t feel like I can just release it without some more clarity and focus, as well as a nice sample project. So, I’m going to try to get it out there piece by piece if possible. I’ve put up a little bare bones project on GitHub – my first! – to test the waters. Let me know what you think, and of course, feel free to fork it and make it better. Right now it’s just a simple version of the rotation control view (RDDRotationControlSurface) which is hooked up to a UIViewController delegate that spins a UIImageView based on the input. Wow, that sounds way more complicated than it is – it’s just spinning a little picture of a very nice-looking German (or Austrian; can’t remember where this picture was taken) man in a cool getup. Don’t ask me why I chose this picture; it was there, and I went with it!

PS: You may be wondering why I didn’t go with a UIGestureRecognizer subclass for this. As far as I can tell, the gesture recognizer API would not work very well with something like this which needs to continue sending updates even after all touches have stopped. So, in the end, I’d still end up with a UIView subclass of some kind. Doesn’t mean GR couldn’t help here, but I just didn’t go that route.

Macro for Device Specific Settings (There’s a new iPhone Screen Size!)

iPhone 5

Well, it finally happened. Apple is releasing an iPhone with a different screen size and aspect ratio. “Oh no!” everyone screamed. iOS is headed down the path of Android! Fragmentation is here!! OK, there’s probably (almost ) no one actually saying that. Yes, there’s a new device, but the fragmentation situation for Apple – even including the various combination of screen size, processor type, iOS version, etc. – doesn’t even come CLOSE to that of Android. The fact is, Apple know what they’re doing. Agree or disagree with their reasoning for the iPhone 5’s new screen, it’s clear that they don’t take this type of change lightly. I mean, just listen to how Sir Jonathan Ive opens this video. How can you not agree with everything this man ever says?!

The first big “disruption” to the iOS ecosystem, was of course, the iPad. But guess what, Apple took careful measures to make sure that every single existing app would automatically run. I’m sure there were examples of apps that didn’t take to the simulated iPhone environment perfectly, but for the most part, everything just worked. And that was no small feat of engineering, I’m sure! Yes, we were all pushed to build native apps for the iPad, but they weren’t going to immediately alienate thousands of developers and millions of app users just because they decided to make a cool new device. The next disruption was iPhone 4 and Retina Display. Once again, great new technology for those who incorporate it, but in the meantime, existing apps for the most part ran just fine. And now, last week, the 4″ screen of the iPhone 5. But guess what, all existing apps will run just fine, only letter-boxed. But what about those who want to take advantage of this new technology, to create an app that makes full use of that new tall screen? Continue reading

Click – A Postmortem

The App

My latest app, an iPhone metronome called Click, has been out for two months now, so I thought this would be a good time to do a little postmortem reflection on the development process, the launch, and some thoughts for the future. I’ve discussed some of the development and design of the app before on my blog, but I haven’t yet done much discussion of how it all turned out. So, here goes…if you’re mostly just interested in the numbers, then skip to the end (although I’ll give you a hint: they’re not too large).

What Went Well

1. The Design

There are still some things I want to tweak, but overall I’m very pleased with how the general look and feel of the app came out. It was incredibly satisfying to go through the whole process of brainstorming ideas, testing them out, and then finally settling on a design and control scheme and actually seeing it come to life. It was definitely a learning process, and even though it was slow going, I can look back on my time spent with this project and know that it wasn’t wasted time. I was focused on creating a certain “look” for this specific app, but everything I learned about Core Graphics, UIKit, and Photoshop is instantly transferable and applicable to future projects. There were certainly times that I wanted to give up on the customization, throw in a few stock UIButtons and ScrollViews and just ship this stupid thing, but in the end I’m glad I stuck it out! Being able to turn your vision of what something could be into a real, working product is, for me, one of the greatest joys of software development.

2. The Features/Scope

I spent quite a lot of time and effort thinking through exactly which options and features I wanted to include in this app. The only real required feature of a metronome is that it produce sound at a regular interval (and yes, probably also with some type of visual feedback), and the only required option is to be able to set the tempo to the desired speed. This is all that a traditional hardware metronome does. But modern metronomes – of the software and the hardware variety – have so much more audio flexibility: time signatures, variable accent patterns, subdivide the beat in various rhythms, multiple sounds, storing setups for creating set lists or practice routines, programming longer sequences for specific songs, and on and on. There’s also many varieties of visual feedback available, especially in the realm of software metronomes. I made the decision that one of the key distinguishing features of Click would be the ability to select Continue reading

Interview with Beginning iOS Dev

20120710-211544.jpg

Sunset on The Great Salt Lake

I’m on day two of a three day move from Illinois to California right now, so I don’t have anything new ready for the blog. But, I didn’t want to miss my blogging slot completely, so I thought I’d link to an interview I did the other day over on the Beginning iOS Dev blog. Of you haven’t seen the website yet, you should take a minute to browse around. There are quite a few resources, and the interviews especially are interesting and very well done. There’s also a bit of a postmortem there of my app Click that’s been out for a while now if you’re interested in that. I may do a full write up on here sometime soon. In the mean time, one more full day of driving and we’ll finally be at our new home!

Some Good News and Some Bad News

I’m sure everyone is busy playing with the new bits from Apple right now, or lusting over the new hardware just announced, so I’m not sure who all will see this, but it’s my slot today for iDevBlogADay, and I’ve got some news to share, so I’m going for it!

I’m so mad at myself right now. The good news is, my new metronome app “Click” was just approved and is Ready for Sale!! The bad news is, I used a promo code to download it before releasing it for sale, and… it’s got a bug. A big ol’ freaking whopper of a bug. Somehow as I finalized my image assets, one of the resources had the wrong name in the Nib file – there was an “@2x” left on the end of the image name in the Nib configuration for the UIImageView. The app runs and loads fine in the simulator, and I swear the final build worked fine on my device too, but apparently the App Store release build is more picky and couldn’t locate the resource. So, one of the key pieces of the interface is invisible. So guess what? I’ll be waiting another week at least for another review. I could possibly ask for an expedited review, seeing as this is a “critical bug,” but the problem is the app isn’t actually even for sale yet, so it’s not like the bug is actually “live.” I don’t really wanna push my luck and/or annoy the review team now and then really need an expedited review later. So, one lesson is, keep testing the crap out of your app even after you submit, and you just might catch something and be able to developer reject your binary before the review starts. The other, real moral of the story is: delay the release of your app at least enough to generate a promo code and try out the released version for yourself. I have no idea when promo codes started working for apps before they’re actually released, but it certainly saved me this time! My thanks to @wtrebella for bringing this to my attention when he was tweeting about releasing Polymer.

I must say though, this isn’t all bad. I’ve been working on this app for over a year. I’ve been wanting to integrate a quality metronome into another app of my, theDrumDictionary, and in future music-related apps. So, this was supposed to be a quick side project in learning Core Audio and how to make a metronome, and since I was going to do it anyway, I figured, why not release a standalone metronome app too? But I didn’t want to make just another metronome app, and as I explored how to differentiate mine from the existing options, it sort of exploded into this very large project with difficult to implement (for me) custom controls and a large amount of Photoshop time designing a unique UI. Needless to say, I’m ready to get this thing out there and see what happens! When it comes to an initial release, I actually came to appreciate the sort of built in waiting period of the app store review time. Being forced to stop coding, it was a great chance for me to finalize my press materials and continue to get the word out about the new app. I was expecting to be done a *lot* sooner than how it turned out, and by the time I submitted the app for review, I knew I was going to be running right up against WWDC. Who’s going to care about some no-name company’s metronome app in the middle of big hardware and software announcements?! If approved during dub-dub, how long should I wait to release the app? Or should I release the app, and just wait until later to do press releases, etc.? Or is it really most beneficial to do a launch all at once – app appearing on new releases, press release, etc? (Great articles from Justine Pratt on marketing, by the way!) Well, now I don’t have much choice! I’ve probably got another whole week to keep up the marketing prep, spread the word to existing DrumDictionary customers, etc., and there’s not much worry about WWDC anymore. I’ve got to release this sometime, and a whole week after the big keynote seems like as good a time as any to me; it’s certainly much better than anytime this week. And, I can confidently run a full on launch blitz with no fear that I’m messing it up by separating the app release from the press release OR driving myself crazy as I wait for days for the right marketing timing knowing that it’s just sitting there ready waiting for me to change the availability date. I suppose I shouldn’t be too mad about it after all! (but let’s face it, I’m pretty pissed). Anyway, maybe this gives you something to think about before you release your next app! And, if you’re curious, head on over to my new Gig Bag Apps website and check out the trailer for Click. Maybe it’ll be a hit; if I ever actually release it🙂

UIKit and GCD

Graphics Bottlenecks

Creating a responsive user interface is one of the most important considerations for a mobile developer, and the smooth scrolling and quick responsiveness of iOS has been one of its hallmarks since day 1. — I’ve gotta be honest here; I still find myself every now and then finding great amusement in just flicking around a simple web view or scrolling some text on my phone. It just feels so right! — Keeping a smooth flow and one to one correspondence between user touch and visual display is crucial for maintaining the illusion and feeling that one is directly interacting with the objects on the screen. One key consideration to make this happen is do not block the main thread. If you are doing anything that might take a significant amount of time, you must do this on a background thread.

With iOS 4.0 and the introduction of blocks and Grand Central Dispatch, it became much easier to complete tasks in the background asynchronously without having to dive into the implementation details of threads and such. If you haven’t yet tried out GCD, take a look at the docs, or check out this tutorial to get you up and running quickly. It’s great for parsing data, downloading from the network, etc. off the main thread, and GCD makes it very easy to write code that will call back into the main thread once the background process completes. What it doesn’t work well for is anything to do with UIKit or the user interface. All drawing and touch interaction takes place, by design, on the main thread. So, what do you do if your drawing itself is taking too long and blocking the main thread? I’m sure there were people much cleverer than me who found some ways to get around it and do some drawing in the background, but basically up until iOS 4, UIKit was not thread-safe at all. If your drawing is too complicated and blocks, then you need to optimize it or simplify it. However, the release notes for iOS 4.0 contain the following short section:

Drawing to a graphics context in UIKit is now thread-safe. Specifically:

  • The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads.
  • String and image drawing is now thread-safe.
  • Using color and font objects in multiple threads is now safe to do.

This was not something I had really been interested in or concerned myself with until I ran into just such a problem recently. I created a custom subclass of UILabel which adds a colored, blurred shadow to the label to give it a glow effect. But, this drawing took drastically longer than the regular string drawing. For example, for the drawing that happens at app startup, using regular UILabels takes 104 milliseconds total in drawRect:. To draw the exact same strings with shadows takes 1297 milliseconds! So, you can imagine what this does to frame rates when there are multiple labels being updated rapidly during an already CPU intensive section of the code.

Multi is fun threading!

Since I already know ahead of time exactly what strings I need to display during this particular bottleneck, it would be nice to be able to draw all the labels at once in the background and cache them for later. My first approach was, Continue reading

Follow

Get every new post delivered to your Inbox.