Streaming is available in most browsers,
and in the WWDC app.
Bring your iOS app to the Mac
Discover all the different ways you can transform your iOS app into a great macOS experience. We'll explore best practices for bringing your app to the Mac, whether you ship an iPad app for M1 Macs or build something for all Macs using Mac Catalyst. Learn about the latest tools, options, and APIs to help you deliver enhanced experiences. We'll also show you how you can optimize your app for the Mac, and find out how desktop class iPad features automatically transform into Mac-native options when built using Mac Catalyst.
- Have a question? Ask with tag wwdc2022-10076
- Mac Catalyst Human Interface Guidelines
- macOS Human Interface Guidelines
- Search the forums for tag wwdc2022-10076
- Supporting desktop-class features in your iPad app
♪ ♪ Owen: Hello, and welcome to Bring your iOS app to the Mac. My name is Owen, and I'm a Mac Catalyst engineer.
Whether you ship your iOS app on M1 Macs with no changes, have started thinking about going further with Mac Catalyst, or already ship a Catalyst app you want to make even better, I'm excited to share new APIs and techniques to make your app the best it can be on Mac. But first, I'd love to show off some of the amazing work done by developers that showcases what's possible with Mac Catalyst. Craft is an incredible app that makes it effortless to start writing and produce beautiful documents, and is the App Store's 2021 Mac App of the Year winner. And because of Mac Catalyst, this great experience is available across devices, so it's always ready when your next idea strikes. Darkroom's smart AI editing tools streamline your photography workflow, and you can start your edits in the field on your iPhone or iPad, and finish at home with their Mac Catalyst app. It won an Apple Design Award for outstanding design, innovation, and ingenuity, and has been an App Store Editor's Choice app since 2018.
Night Sky is a stunning way to explore the cosmos right from your computer. You can learn about the constellations, and get a closer look with detailed 3D models of the moon, planets, and satellites. It has won multiple Webby and Lovie awards for its design and breathtaking visuals.
Asphalt 9 - Legends is an exhilarating high-octane racing simulation, and the only racing game to ever win an Apple Design Award, and the action is even more exciting on the big screen with their Mac Catalyst version.
Now, I'll get into all the ways you can create a great experience on Mac for your app. I'm going to start with a couple of new options for running your iOS app natively on M1, the easiest way to get your existing iOS app onto Mac.
Then I'll walk through adding a Mac Catalyst run destination in Xcode, and go over what changes.
I'll show off the new behaviors your Catalyst app will get for free when you adopt the new Desktop-class iPad APIs.
Then dig in to Mac-specific refinements made possible with new Mac Catalyst APIs.
I'll start with some new options for native iOS apps on Macs with M1.
Your iOS apps are already available on M1 Macs in the Mac App Store. As long as you haven't opted out, your app is found in a search under the "iPhone and iPad Apps" tab. And we have a couple new additions that can improve your app experience on Mac. There are two new keys you can add to your Info plist, which allow you to specify how your iOS app should launch on Mac. These keys aren't bound to any SDK version, and are ignored on iOS and on Mac prior to macOS 12.1, so they're safe to add to any app that would benefit.
The first key, "UISupportsTrueScreenSizeOnMac," indicates that your app is prepared for the wide variety of display configurations it may encounter. This way, your app gets the true screen size and pixel density, rather than a compatible iPad size.
The second key, "UILaunchToFullScreenByDefaultOnMac," tells the system that your app prefers to enter fullscreen mode as soon as it's launched. These two keys work great together, especially for games and multimedia apps, delivering a pixel-perfect, edge-to-edge, full screen experience.
These keys have been adopted by the award-winning Sky: Children of the Light to provide an immersive experience immediately. As soon as the game is launched, it pulls you in to its beautiful world of exploration by filling the screen with rich detail. Another way to improve your app experience on Mac is with Touch Alternatives, which automatically converts keyboard, mouse, and trackpad input into iOS multitouch gestures and device motion expected by your app.
We've already added built-in touch alternative support for many of the most popular games on the app store. When launched, they automatically show a tutorial explaining how their touch controls translate to a keyboard and mouse or trackpad. For example, the arrow keys can be used to simulate swipes from the center of the window, and the spacebar to perform a tap.
To opt into automatic Touch Alternatives, create a new plist file in your app named "com.apple.uikit.inputalternatives.plist".
First, add a key called "defaultEnablement" with a string value of "enabled", which tells the system that Touch Alternatives should be on immediately.
Below that, add another key called "requiredOnboarding". This is an array containing a list of which controls you've decided work best for your app.
You have the choice to onboard for five different control options: tap, tilt, drag, swipe, and direct touch input from a trackpad.
Note that when Touch Alternatives is enabled, all of these controls will be active, but you should still decide which make the most sense for your app, and only add the controls that you want highlighted to your onboarding plist. This is detected when your app is run on Mac, and on first launch, the onboarding sheet is presented highlighting those controls. In your app settings, people can switch between displaying the preferred controls specified in the plist and all controls.
Of course, the best option is to implement keyboard and cursor support directly in your app. By doing this, you ensure your app behaves well on all devices, including iPads with an attached keyboard, and on the Mac.
For more information, watch the videos "Support hardware keyboards in your app" and "Handle trackpad and mouse input". Now I'll quickly cover the process of becoming a Mac Catalyst app.
By adding a Mac Catalyst destination in your project settings, your app will automatically be converted to a full Mac Catalyst app capable of running on every Mac, and allowing you to customize it further using Mac Catalyst API. You also have the choice to optimize the interface for Mac, which will give you native AppKit styled controls, and ensure your app content renders at native scale.
I'll be using the Markdown demo app that the team has been working on to highlight the new iPad features. When I first bring it to Mac, it's running in "Scaled to Match iPad" mode.
When I switch to Optimize for Mac, many changes happen automatically.
When compared side-by-side, the differences are apparent. When the app is optimized for Mac, the UINavigationBar gets translated into a rich NSToolbar, providing native AppKit controls. This translation happens for other controls as well. And the text size adjusts as well. Text in the iPad idiom renders at iPad size, and then is scaled down to 77% of its original size. Text in the Mac idiom is handled with native Mac font rendering, which happens at pixel-perfect scale. This is ideal for our app, since it ensures the text always looks crisp. With the app opted into Mac Catalyst, I want to check out how well it works, and go deeper into the new automatic Mac behaviors provided by iPadOS 16's new API. If you've already watched "Meet desktop-class iPad" and "Build a desktop-class iPad app", you've learned about the many new tools to enhance your app with iPadOS 16. And these new APIs translate beautifully into native Mac representations. I'll take a tour of the markdown app, and highlight some of these new behaviors.
Controls and navigation move from UINavigationBar into the NSToolbar. And if you don't already create a toolbar, we give you one automatically. If you already manage your own NSToolbar in Catalyst, we stay out of your way.
Center item controls become NSToolbarItems.
For document based apps, your window title shows the document name, and if "Show window title icons" is enabled in Accessibility System Settings, the file proxy icon appears as well, exactly how you would expect it on Mac.
And if you use a navigation controller, the back button and other navigation controls are also brought into the toolbar. Additionally, you get new document-centric menu items in the File menu: Duplicate, Move, Rename, and Export As.
To enable these menu items, ensure some object in your responder chain overrides UIResponder's duplicate, move, rename, and export functions.
If your app doesn't need these File menu items, they should be removed with UIMenuBuilder. Implement the buildMenu method on your app delegate to control your app menus.
The new Document menu items have a UIMenuIdentifier value of .document.
If your app includes a search bar, it gets automatically pulled into the NSToolbar as well, first showing as a search button that expands into the bar on click. The UISearchTextField that backs it is hosted inside of an NSToolbarItem, and this is available for custom views as well. The search suggestions menu and search scope bar also get converted into native AppKit controls.
In addition to all the new Mac behaviors you get for free by adopting desktop-class iPad features, we've also added several new Catalyst-specific APIs to improve multi-window and toolbar behaviors. I'll go through our Markdown app one more time, and add these Mac-specific features using a mix of old and new API. From the existing Mac Catalyst APIs, I've chosen a few that really enhance our App.
I've adopted the Mac idiom to get native controls and the automatic NSToolbar. I added a custom pointer so moving the mouse over the slider handle in the middle of the custom split view switches the pointer to horizontal double-arrows indicating that the split can be resized.
And I've added printing support with the UIApplicationSupportsPrintCommand plist key.
When considering your app, don't feel like you need to add every single one of these features. Instead, think about the type of app that you create, and which features work best for it. Check out the Mac and Mac Catalyst Human Interface Guidelines, and look for inspiration in other apps you use.
With these features implemented, the app is already in a wonderful spot. And now with some new Mac Catalyst API, I can do even more. We've added new options for customizing app window frame and controls, for displaying UIView content in the NSToolbar, and for showing popovers from toolbar items. I'll go ahead and use these new APIs to improve our app even further on Mac starting with the windows.
Catalyst apps support multiple windows using the existing UIWindowScene API. And new in macOS Ventura, we've added API to let you customize your app windows even further by setting the style of the traffic-light window controls, programmatically resizing and repositioning your windows, and disabling fullscreen for specific scenes.
I'll use these tools to add a feature to the markdown app to show a helpful auxiliary panel with markdown syntax. This panel will be sized smaller with the new geometry request API, and have its minimize and zoom buttons disabled.
At scene creation, in my Scene Delegate's "scene willConnectTo session" method, I create my desired frame. It's good practice to always start with the current frame from effectiveGeometry. Before the scene is created, this is initialized to CGRectNull, whose values the system knows to ignore for initial scene creation. I modify the size, then give my scene its new frame by creating a new UIWindowScene.macGeometryPreferences object and passing the frame as its systemFrame argument.
I then submit the update using the scene.requestGeometryUpdate() method. Because this is a request, the system reserves the right to reject the new geometry, in which case it will call the error handler callback with details. When done in the scene willConnectToSession method as shown here, the request will apply to your application's first launch, but will be superseded by any applicable state restoration performed by the system on later launches.
And because this is a small helper panel, I also disable the minimize button from the new windowScene windowingBehaviors object, and the ability to make the window fullscreen, from the new property on sizeRestrictions.
When this new Markdown Hints window is shown, it appears with the size we requested. The yellow minimize and green zoom window control buttons are disabled, leaving only the red close button.
These options aren't reserved just for scene creation. At any time in a scene's life, you can check its current frame from the readonly effectiveGeometry property, modify it however you need, and request a new geometry update. Here's another example showing how to modify the origin of the window, keeping its size the same.
There are two important aspects of the geometry to keep in mind. First, because systemFrame dictates the frame of the window on the Mac desktop, the size of one point for the systemFrame property is always the size of one AppKit point. If your app is optimized for Mac, this is the same scale as your UI elements. However, if your app is scaled to match iPad, it will differ by the 77% scale factor. Second, the origin of the coordinate space is the upper-left corner of the main display. If you have multiple displays, the main display is the one that shows the Menu bar in the system display settings.
With new Mac Catalyst API, you can take control over the state of each of the three window control buttons. The new windowingBehaviors object on UIWindowScene has two properties, closable and miniaturizable, that will adjust these respective window behaviors and enable or disable the red and yellow window buttons.
The green window button handles both resizing your window on the desktop, and taking the window into fullscreen. You can disable fullscreen with the new property on sizeRestrictions, "allowsFullScreen" or disable resizing by using size restrictions and setting the minimum and maximum size to the same size. And by doing both, the green button also becomes disabled.
And you can check whether your scene is currently fullscreen with the new "isFullScreen" property. Now, I'll focus on refining the toolbar for Mac. We've added new options for toolbar customization, whether you rely on the automatic conversion from a UINavigationBar or manage your own NSToolbar in your app code.
New in Mac Catalyst, UIViews can be added as items to the NSToolbar. I designed a custom UIView for our App that shows the current word count. And when clicked, it presents a popover with additional details like paragraph and section counts, reading time, and translation. Because I'm using the new desktop-class iPad API, the customView property on my UIBarButton item is automatically wrapped and added to the toolbar. But if you manage your NSToolbar independently, we've also added a new NSToolbarItem subclass, called NSUIViewToolbarItem.
You can use NSUIViewToolbarItem just like any other NSToolbarItem, to instantiate a toolbar item from your NSToolbarDelegate's itemForIdentifier method. The initializer takes a UIView to wrap, which is then inserted into the NSToolbar.
NSToolbar expects unique toolbar item instances for toolbar customization mode. If you are using automatic NSToolbar hosting from your UINavigationBar, your view is cloned by the system for toolbar customization automatically. However, if you manage your own NSToolbar, your delegate will need to create unique instances of your UIView for each NSUIViewToolbarItem instance, rather than reusing the same UIView instance.
With my new item in the toolbar, I'll add the popover behavior. In my toolbar item's action, I create the popover view controller, and set its source item to be my toolbar item. Then I present the popover.
With the popover code in place, clicking on the toolbar item presents additional detail in a popover presentation anchored on my toolbar item.
Like other controls in Mac Catalyst, you can opt out of navigation bar translation by using the new property preferredBehavioralStyle on UINavigationBar. Its default value is automatic, but you can set it to .mac to explicitly request translation. and by setting it to .pad, your navigation bar no longer gets automatically translated.
With these options, you can add a new layer of customization to your app's toolbar.
We're so excited to see how you use these new tools to make your apps even better. With your iPad app automatically on the Mac App Store, it's available for a whole new audience. When you upload your iPad app, run it on the Mac and try it for yourself. Or take it to the next level by becoming a Mac Catalyst app, and use the new API in iOS 16 and macOS Ventura to make your app its best.
It's easy to bring your app to the Mac. We love showcasing your hard work and can't wait try what you build next. Thank you.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.