The Rude Awakening for iOS Devs
Apple is attempting to bring their huge success with iOS over to the Mac. Hence “Back to the Mac,” the Mac App Store, and the iOS-ification of Mac OS X. A big part of what has made iOS successful is the outstanding selection of quality apps. There are show-off apps to make your friends jealous. Time-wasting apps for when you’re stuck at the mall with your significant other. Get-stuff-done apps for those rare moments you might actually want to, you know, get stuff done.
To create all these great apps, Apple had to create a great environment for developers. Marco Arment has written previously on why developers flocked to the original iPhone. I believe one of the reasons is that Apple provided a set of APIs that made it easy for developers to quickly create fast, beautiful, animatable UIs.
Now Apple’s trying to bring that success to the Mac which means bringing over the ocean of iOS developers. iOS developers are in for a rude awakening.
AppKit is UIKit for Mac, minus all the good parts
UIKit is the UI framework for iOS, AppKit is the UI framework for Mac. But that’s where the similarities end.
AppKit is from an older time when RAM was scarce, CPUs were slow, and GPUs didn’t come in consumer machines–and its design reflects that. I could rant for a while about all the odd and outdated design patterns used in AppKit (I mean come on NSCell, what the hell is wrong with you?!). But at the end of the day, AppKit’s a product of its time, just as everything is. You can’t blame it for that.
UIKit is a brand-new framework created entirely for iOS. It was Apple’s chance at a clean slate and they took full advantage. But that means literally no UIKit code translates cleanly to AppKit. And that’s probably ok. An app coming from iOS should be re-designed for Mac so it’s only fair that the UI code be re-written as well. The real problem is that most of the niceties developers having come to expect by working with UIKit are lacking in AppKit.
Core Animation is really cool, mmk?
iOS uses animations gratuitously to great effect. They make the whole OS feel alive and physical. But the trick to animations is that they have to be fast or they ruin the whole illusion.
(That’s one of the reasons Android devices have just felt wrong up until recently. They had animations but they were slow and jerky. They didn’t make the device feel alive and physical–they made it feel slow and stodgy.)
The secret behind the smooth-as-butter animations in iOS is Core Animation. The name is a bit of a misnomer. While it does handle animation beautifully, Core Animation is actually a whole rendering system that involves much more than just animation. To completely oversimplify it, Core Animation has these things that programmers can use called CALayers. The great thing about CALayers is that they don’t have to be redrawn all the time. They can get drawn once and then cached on the GPU. This lets drawing be crazy fast, and that lets us do crazy smooth animations. Core Animation is great and it’s how all drawing on iOS happens.
(And to compare this again to Android, it was only very, very recently that Android has been able to use the GPU to render UI, and even then only on select devices and with some caveats. This is one of the reasons Android’s animations haven’t been smooth. They had to be drawn by the CPU. This meant the app and the animation had to fight for CPU cycles and the CPU had to draw UI, a task it’s not specifically suited for.)
Now, Apple’s no fool and they knew that Core Animation was great, so in Mac OS X 10.5 they brought Core Animation to Mac. This was great news. Before Core Animation the only Apple-provided method for animation was NSAnimation, which, frankly, was just gross. It was buggy but even worse, it committed the cardinal sin for animations: it was sllllllllow.
So that’s ok. Core Animation is great and it came to Mac a few years ago. So then what the hell am I complaining about?
Apple makes it really hard to make nice things
The problem with Core Animation is also one of its strengths. You remember above when I talked about how Core Animation is crazy fast because it can cache to the GPU? It turns out that that paradigm is wildly different from how drawing typically happens with AppKit. Because it’s so different it leads to lots of interesting quirks and bugs when we try to use AppKit and Core Animation together. Meanwhile UIKit doesn’t have this problem because it was designed from the ground-up for Core Animation.
Let’s be really clear here:
- AppKit handles all the native Mac UI.
- Core Animation gives us fast drawing and smooth animations.
- Using Core Animation with AppKit is super buggy.
We end up having to choose between smooth animations and Apple’s UI framework. That really sucks.
Is it really all that bad?
Yes. Before I give you a few examples, I need to explain a little bit more about Core Animation and AppKit.
When you use Core Animation and AppKit together, you choose between using it with “layer-backed” views and “layer-hosting” views. Layer-backed means that there is a CALayer (remember those magical guys from above!) lurking behind the scenes of your AppKit view. You get pretty smooth animations and drawing, but AppKit “owns” the layer so you can’t actually access Core Animation directly. This is kinda limited. Meanwhile, layer-hosting means that you own the layer and get to use Core Animation directly but you can’t add any subviews to the layer-hosting view. That means not using any of the standard AppKit stuff. Really limited.
But it gets worse.
Suppose you decide that layer-backed views will work for you. You don’t need to directly access Core Animation so it’s a fine tradeoff for animations. I mentioned above that using Core Animation and AppKit together lead to funny bugs. This includes things like text views not drawing the spell-correction line when used with layer-backed views. And things like scroll views scrolling the wrong way. And text fields getting a weird-looking focus indicator. And text rendering looks blocky and gross because it’s not drawn using subpixel anti-aliasing.
Kyle Sluder, a developer at The Omni Group, wrote a few months back on Apple’s cocoa-dev list:
My professional suggestion: avoid using Core Animation for anything related to traditional UI. CA is great for things like Front Row, sprite-based animation/games, overlays atop Core Video movie playback, data visualization (but be careful here! sometimes it’s also the wrong tool for building data visualization)… it’s not good for writing the next version of your productivity app’s main content view.(http://lists.apple.com/archives/cocoa-dev/2010/Dec/msg00464.html)
So yes, the situation is that bad.
Do it yourself, bitch
So here we are, a couple hundred words in, and you might be thinking to yourself, “Damn it, man, stop your bitching and just re-implement AppKit using Core Animation!”
Some people have done just that, most notably Twitter for Mac and Twitterific for Mac. Both have their own re-implementations of UIKit for Mac using Core Animation. (You can confirm this by class-dumping both of them.) Unfortunately neither of them are open source. (Edit: one day after posting this, The Iconfactory open-sourced their implementation of UIKit for Mac. It’s pretty awesome: Chameleon). There is a good start on an open source, Core Animation-based port of UIKit on GitHub but it’s still far from being usable in a production app.
(I’m going to ignore for the sake of brevity that creating nice, fast, animatable UIs on Mac shouldn’t be this hard and that Apple’s had more than 3 years to fix this and that the onus of reimplementing AppKit with Core Animation shouldn’t fall on third-party developers.)
You might also be thinking, “Well, there is a certain big cat OS scheduled to come out soon. Maybe they fixed it in that.” But let’s suppose that that is true and that a few weeks ago Apple released a beta of said OS to developers but that said OS still has many of the same problems with Core Animation as it did before. (My only hope now is that Apple’s waiting to announce it at WWDC in order to rock my socks off in person. That’s what’s happening here, right Apple? …right?)
Wrapup
So where does that leave us? We have re-implement AppKit (or something like it—maybe something better like UIKit) with Core Animation. That’s not insurmountable but it is a significant investment of time and resources.
What does Apple expect us to do? Does Apple expect all third-party developers to make that investment of re-implementing some UI framework with Core Animation? Or use the quirky and buggy combination of Core Animation and AppKit? Or give up on animations? Or give up on the Mac altogether?
(Addendum: Hey any AppKit engineers out there reading this! I heart you guys. For serious. I know I’m giving you a hard time on this, but it’s because this is a really big deal. That said, you have given us some great stuff over the years. Oh and you know that one really, really awesome new thing in that upcoming OS? That blew my mind. I’d love to talk more about this whole thing in person. Find me at WWDC and I’ll buy you a beer.)
Mostly I work on GitHub for Mac. Mostly.