Hacking Marzipan — Running iOS apps on Mac

In this presentation, Q-er Tom shows how he managed to get iOS apps running on Mac by hacking Apple’s unofficial Marzipan technology.

Hacking Marzipan — Running iOS apps on Mac

Running iOS apps on Mac

In his presentation at the 2018 Do iOS conference Q-er Tom Lokhorst showed how he experimented with Apple’s Marzipan and what he had learned. Check out his talk or read the recap below.

As a Mac user, I like Mac being a healthy ecosystem, having people develop Mac apps and Apple improving the Mac. However, the situation now is sort of the other way around. There are less and less Mac apps and, less and less developers working on those apps. Is there a way to turn around this dwindling engagement in the developer community?

Personally, I’m most excited about the possibility of developing mobile apps for the Mac as well. At technology agency Q42 we primarily build iPhone apps, but we add the iPad app as well because it’s just not that hard to do. There is a lot of tooling and support for adding an iPad app to your iPhone app. It would be very cool if we could do the same to add a Mac app.

In my presentation I will tell you something about the history of Marzipan, about some other approaches, and about how you can have one app across three platforms: iPhone, iPad and Mac. To temper your expectations: Marzipan is not something you can use today for apps in production.

In 2017, Mark Gurman wrote an article in Bloomberg talking about Apple working on a way to combine iOS and Mac apps into a single user experience. He said: software developers will be able to design a single application that works with a touchscreen or a mouse and trackpad. That was also the source of the name Marzipan.

One of the articles that followed up on that thought, was John Gruber on Daring Fireball. According to him, Marzipan doesn’t make any sense: iOS has no concept of a mouse cursor and only runs on touchscreen devices and macOS has no support for touchscreen devices and requires a mouse and a keyboard. What this probably is, is Apple creating cross-platform frameworks. You have iPhone apps you write in UIKit, Mac apps you write in AppKit. Those are distinct for historical reasons. What’s probably happening is that Apple is merging those, according to Gruber. Apple may be working on a new UI library, launching in 2019 or even later. I was very excited by that idea, because I don’t really like UIKit with all the imperative code. I would like a declarative API, something new with data binding and stuff.

At WWDC 2018, Craig Federighi, Apple’s senior vice president of Software Engineering, said: No, we’re not merging iOS and macOS. Instead we’re working on bringing more apps to the Mac. With a sneak peak of Apples Home, Stocks, Voice Memos and News iOS apps running on macOS, he showed the new technology behind the Marzipan rumor. He also mentioned that other developers could use this build-once-run-anywhere technology from 2019, giving us hope it will be announced at this year’s WWDC.

This leads to the question: aren’t those cross-platform apps always crap? The answer is: yes, most of the time they are. If you start using the Voice Memos app on your Mac for example, you see that buttons are gigantic. If you click edit the whole screen changes, which is really weird for a Mac app. I tried to play/pause using the spacebar, but that doesn’t work. So, it’s not a really good app.

Nevertheless, I think it will get better. Instead of starting from AppKit and shrinking it, they are starting from UIKit originally developed for the iPhone and adding stuff to it to make it better. I think that’s the right way around.

So, let’s have a global overview about how it works, how it works currently because as I said, it’s still under heavy development. This is from the State of the Union, explaining sort of the general way in which it works.

The current tech stacks for macOS and iOS apps

The lower level frameworks like Core Foundation, Core Location, all that stuff has been unified. Those APIs had diverted over time, but they have been all unified because they’re basically the same between macOS and iOS. And now macOS has a new way of creating user interfaces. It already had AppKit, WebKit and things like Metal for games, but now it also has UIKit. So you can build an app in UIKit that runs on your Mac. What they’re doing is adding all these extra features to UIKit on the Mac. So now you can populate the menu bar on your Mac and your app properly resizes when you resize the window, for example.

So, let’s look how it currently works. Whenever you start an app it starts two processes. One is the UIKit process and the other is an AppKit wrapper around that UIKit process. The thing with the lowest process ID is the UIKit app, the original app that also runs on iOS, on the iPhone. The other app is a wrapper around it and those apps together work together to create a single experience for the end user. In my demonstration I’ll dig a little deeper into this.

A lot of developers have been trying to find out how it actually works. One of them is Steve Troughton-Smith. He realized that UIKit iOS apps have been running on the Mac for a while in the iOS simulator. So, Xcode can build your apps for ARM processors, for running on iOS devices but also for the iOS Simulator that runs natively on the Mac. Steve Troughton-Smith created a tool to just change your simulator build a bit so that you can start them on your Mac as a Mac app. When he published this, I got very excited and immediately started trying to get this to work on our own Q42 apps.

As an engineer at Q42, I have access to a lot of real-world apps and I just started trying to get them to work using the Marzipanify tool. Unfortunately, I got stuck with most of the apps. Therefore, I realized I shouldn’t aim so high and I picked a small part of the Rijksmuseum app: its ArtViewer library. It uses tiling to efficiently showing high-res images. With this separate app, it worked! The app uses Swift, UIKit and things like CATiledLayers. The only thing I had to do: Get the code for that app, build it for the iOS simulator, run it through Marzipanify and start the app. You can resize the window, it starts downloading more or less tiles, exactly as it was designed for the iPhone or the iPad. It works the same on the Mac!

Once I got this to work, I started experimenting with my own app Trein, a pet project I built with my brother. To get this app running on my Mac I had to rip out the Realm database because it doesn’t work on the Mac, but also smaller things like the Haptic Feedback Generator, Intents, Safari View Controllers, MapKit and some entitlements.

For a demonstration of how to get an iOS app to run on a Mac, see the video at 20:30. Also, check out the code for the demo project.

Train app on both iOS and macOS using Marzipan

So, this is where we’re currently. It’s not yet supported. You can play around with it but it’s definitely not ready for production apps with all the private frameworks. In the future I hope to have my Trein app and our Q42 apps working on iPhone, iPad and also an app shipping in the Mac AppStore. I do think Marzipan will get better over time. Apple will start adding more and more stuff to UIKit on the Mac to make it more Mac-like. Let’s see what this year’s WWDC brings!

Want to know more about what Tom learned while experimenting with Apple’s Marzipan? Check him out on Twitter!