Rss

Apple Didn’t Kill AppKit, Millenials Did

(yes, thank you for indulging my outrageous clickbait headline, which wildly misrepresents the contents of this blog post)

Two weeks after WWDC, and we’re all still talking about Marzipan, the de facto name for UIKit-on-macOS that was acknowledged in the keynote. Like, seriously, as I’m typing this Colin and Steve are arguing about it, so everyone who follows both of them gets to watch.

Craig Federigi showing diagrams of macOS/iOS app architectures

It won’t even be available to developers for another year, so we have lots of time to argue, and to enjoy the unintended consequence of Osborning macOS’ AppKit framework.

But… what if this is all sound and fury, signifying nothing? What if tasty Marzipan turns out to be a big Nothingburger? Because that could well be how it pans out instead.

The Argument For

So, the case for Marzipan (that’s the code name that came up in all the rumors earlier this year, and what everyone understands, so let’s go with it) is something like this: there are a lot more iOS developers than Mac developers, and they’re writing code that is this close to working on the Mac. Simplify that process and you get a flood of Mac apps for free.

Another version of this argument is phrased as a criticism of macOS’ user interface framework: AppKit is too hard for developers coming over from iOS, it’s too different, it has crappy old legacy stuff that’s waved off as “you had to be there”. NSTableViews don’t work quite like UITableViews, NSViewControllers aren’t exactly like UIViewControllers, and so on. It’s too off-putting for indie developers, and an unwanted expense for corporations to have to find and hire developers who know and like AppKit.

Side-Eye

Maybe I’m not bringing sufficient enthusiasm to the argument in favor, but the above is pretty much it, as I see it.

And this is where I jump off the Marzipan hype train. Because the above is an argument in favor of laziness and cheapness, which are two things we do not typically associate with developing for Apple platforms.

Meiya steadfast

Is it really that hard to share a codebase between Mac and iOS? I just sent off the “other platforms” chapter of Xcode Treasures, and one of the sections is about creating multi-platform projects. The book shows how to add tvOS to an iOS project from earlier in the book, but the idea is the same regardless of which platforms you support: portion off the code you can into cross-platform frameworks, ideally leaving only platform-specific UI code in each platform’s targets.

Xcode file inspector multiple target membership

This is more plausible than you might initially realize, because the platforms share a lot of code under the hood: Foundation, Core Location, StoreKit… these are all on iOS, macOS, and tvOS (and some are even on watchOS). Even the underpinnings of the UI are cross-platform: Core Graphics, Core Animation, Core Text, AV Foundation, etc., all exist across the Apple platforms. That’s why it makes sense for the documentation sets to have merged a few years ago: you don’t need four copies of NSURL docs when it’s the largely same thing everywhere.

Yes, you would want to be thoughtful about how you architect your code so it builds and runs on all these platforms. 10,000-line view controllers are going to be much harder to port than small, embeddable VCs, where you’ll have more control over which to put in their own windows versus embedding in parent VCs, etc. (Dave DeLong’s A Better MVC is a crucial guide here). In fact, I’ve found that using embedded VCs is also critical to making apps that work well on iPhone and iPad — it gives you flexibility with scenes that need a full screen on the phone but maybe could be part of a bigger scene on the tablet.

I can also imagine an MVVM approach being good for a UIKit/AppKit hybrid, because the logic you put in the view models would likely be fairly cross-platform, leaving just platform-specific code remaining in a small view controller.

But here’s the painful part: the techniques to do these things are already available, well-known, and very few people are using them. There are still lots of iPhone-only apps, or apps that make poor use of the iPad and just let their table views stretch out to infinity. And as for tvOS… it already runs UIKit. Your scenes are actual damn UIViewControllers. And yet look at the dearth of TV apps. We’ve had Marzipan on the TV for years and almost nobody uses it.

That’s something that makes me skeptical about the Marzipan dream. Developers who give a crap are already able to make this kind of thing work, and developers who don’t give a crap aren’t going to do it no matter how easy you make it.

IIUC, Twitterrific builds for both macOS and iOS from the same code-base, and the IconFactory is a small shop. But maybe that’s the point: it’s made by a small team that knows, cares, and enjoys what they’re doing. Exactly the kind of people that make the best Mac and iOS apps. Exactly not the kind of people you target a cross-platform framework at.

Repulsed by Electrons

To be clear, the enemy is not other Apple-platform developers. The enemy is the use of bloated, cross-platform, phone-it-in frameworks. “Write once, run everywhere” has been promised and come up wanting for decades: Java applications and applets, Adobe AIR, Xamarin, PhoneGap, and so on. One semi-success story of recent years are the various approaches like Electron and Chromium, which effectively embed an entire instance of the Chrome web browser in an app wrapper. This approach is used by such Mac apps as Slack, Discord, and Spotify.

It is also a goddamned scourge, and straight up an abuse of the end-user’s equipment.

But here’s a thought: is this approach popular because writing webapp code is inherently easier or more productive? Or is it the value in the fact that the webapp code has already been written — for the web page — and this just gives it a suitable environment to run in?

Because in that case, screw the app, you might as well just run the web version:

And this is something that not a lot of us probably want to admit, but a lot of iOS apps are de facto replacements for webapps, and make sense on mobile primarily because of the limits of mobile web browsers and the impracticality of juggling lots of open tabs on the phone.

Back in my Java days, author Bruce Tate’s Beyond Java raised hackles by exposing an unpleasant truth about web development: most of it consists of connecting databases to web pages. Well you know what, a lot of iOS apps consist of connecting databases to UITableViews. The presentation ends up being different, but the concept really isn’t.

In fact, look at the four Marzipan apps being included with macOS Mojave: News, Stocks, Voice Memos, and Home. The first two of those are basically web pages.

Icons of Marzipan apps: News, Stocks, Voice Memos, Home

In fact, they may not even be as good as competitive web pages. If you’re interested in stocks, and you have an online broker, aren’t you going to be better served by the Charles Schwab or Ameritrade page, which will have not just price data but access to your account? Is the News app really competitive with the wealth of news websites? And what is it about being double-clickable apps that gives them any kind of advantage over web pages?

How many iOS apps out there are basically duplicating web pages? What’s the advantage of a Netflix or Hulu macOS app over their web page equivalents? In many cases, their current iOS apps have less functionality than their web versions: you often can only manage users and queues in the web version. Or consider how the Pandora iOS app is basically playback-only: if you want to create a new custom station, you need to use the web page. Why would I want the minimally-functional iOS app brought to macOS, when a more functional equivalent just requires popping open a new Safari tab?

The web is all about content consumption. That’s what browsers, not apps, are for.

Sure, there are exceptions, because some iOS apps do real work (Overcast would be an obvious example). But for the most part, I have a hard time thinking of iOS apps that I wish I had on my Mac.

Anyone keen on replacing their Steam game collection with free-to-play games from their phone? I thought not.

Share and Share Alike

One more thing: macOS development has a ethos of completeness and interoperability that doesn’t exist on iOS. Any Mac app worth its salt supports copy-and-paste and undo-redo, but in my experience, these features are rare in iOS (beyond the degree to which they’re provided by system UI widgets). In fact, I used to do a conference session about copy/paste and undo/redo, framed as an “80’s flashback” because it feels like the secrets of these APIs have all but been lost to time.


If I start seeing Mac apps where Edit > Undo is grayed out, and cmd-C does nothing but beep, those apps are likely going straight into the trash.

The Future!

The thing is — and this proves how crappy a Cassandra I am (and how I don’t have access to any big-time secrets) — when I first read the Marzipan rumors, I assumed they were a misreading of a more interesting, more ambitious project.

Because if I were a software architect looking at these platforms, I’d be pretty frustrated by the cruft, and in particular how the frameworks are unable to take advantage of new programming languages and paradigms.

I had a rant in a now-lost micro.blog reply I sent to Daniel Steinberg, the gist of which is how there are four paradigms for asynchronous events in Cocoa and Cocoa Touch, and three of them are poorly-suited to Swift. Key-Value Observing requires that the observing object subclass NSObject, and implement observeValue(forKeyPath:of:change:context) (a method that necessarily becomes a switchboard once you’re observing more than one key path). Target-action and delegation both require dynamic dispatch: either as storing a selector to call on the target, or to look up whether the delegate implements a given method. That’s great for Objective-C, less so for Swift.

Thing is, both of these languages now support executable code (and captured scope) as a type: Objective-C blocks and Swift closures. That’s why all the new frameworks tend to use handler-style APIs: you pass in a block to be executed when something interesting happens (a task completes, a timer fires, etc.). This last style is the most familiar to developers raised on onClick and leads naturally to modern styles of programming, like the RxSwift that’s so beloved by hipsters.

I can totally see a future UI framework that unifies UIKit and AppKit in a form that makes much more sense for Swift than either does today. That’s something to get excited about. It could be a long way off, if it’s even in the cards at all.

But in the meantime, the prospect of zero-effort iOS ports doesn’t sound like it’s going to bring a lot of value to my Mac. It’s fine that Apple’s doing it, but for the time being, the Marzipan hype train just gets a shrug from me. And if I do feel the need to get moving on a Mac app — I keep thinking about making DVDivvy a real app now that QuickTime’s days are numbered — there’s no question I’ll go directly to AppKit to do it.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.