[ Music ]
[ Applause ]
[ Applause ]
Welcome, great to see you all here.
My name is Ali Ozer, I along with my colleagues, Jake and Jason will be giving you an overview of iPad apps for Mac today.
We have two talks for you.
In this first talk, we will cover the basics, what this technology is, how to get started, some things you get for free, and also some significant API differences you should be aware of.
In our second talk, taking iPad apps for Mac to the next level, which is later this week, we'll cover advance topics such as making your app a better Mac app and also considerations for distributing your app.
So, what is iPad apps for Mac all about?
Well, it's a technology that enables you to rebuild and run iPad apps natively on the Mac.
Let me expand on this.
The Mac is a robust platform for development that enables all kinds of apps.
We have powerful desktop apps, web-based experiences, and also graphic intensive games.
And these experiences, all have dedicated frameworks that support them.
But we've been missing one thing and that's UIKit, the technology used by iOS apps today.
With the UIKit as a native peer to these other frameworks on the Mac, you're enabling you to bring your iPad apps to the Mac as first-class experiences.
Let's talk about how we're doing this.
We have a rich technology stack that's shared between iOS and macOS, and we leverage that as much as possible.
We also bring in iOS frameworks that don't exist on the Mac and integrate them to work well on the Mac with the Mac infrastructure and with the Mac UI design guidelines.
And last but not least, we make it easy for you to get started.
I'll talk about the first two then Jake will come on stage to demo and discuss the third one.
OK. So, let me show you what I mean by technology stack.
Here is the technology stack for the Mac, we have macOS apps, these are built upon frameworks, UI frameworks and also lower level frameworks as you can see here.
Now, these are just some representative frameworks.
We, of course, have hundreds of frameworks in that stack.
In addition to frameworks, we also have databases.
These are things like the user's photos database, context, psreferences, and so on.
And now, we have services, this includes things like the Clipboard service for a copy paste and file coordination.
And then we have the granddaddy service of them all, the Kernel, which is our Darwin Kernel.
Now, the iOS stack looks very similar.
On iOS we have iOS apps and then there is the stack of frameworks and databases and services underneath.
There are some differences as you can see here and I'll talk about this in a minute.
Now, many of you aren't aware that we have been able to run iOS apps on the Mac for a while now in the Simulator.
The Simulator has a distinct copy of the stack running in an environment of its own.
So, it got its own copy of frameworks, databases, and services.
The main goal of the Simulator is to replicate the iOS environment so that you can debug and test your iOS apps as if they are running on iOS.
The Simulator does an amazing job of this.
However, integrating well with the Mac user experience is not a goal of the Simulator.
And neither is running in an optimal fashion for the end user.
So, as a way to bring iOS apps to the Mac natively, we augment it, the frameworks, on the Mac to support the needs of both AppKit apps and UIKit apps.
We combine and unify the functionality of lower level frameworks that exist on both.
Framework such as CoreGraphics, Foundation, libSystem, to create single copy that can serve both stacks.
Now, notice in this picture how UIKit and AppKit in the frameworks that depend on them do not get unified.
Now I'll talk about that in a bit.
Also note ARKit to the side there.
Since there is no augmented reality functionality on the Mac, we did not bring that framework over.
So, there it goes.
Now, don't get us wrong, we love ARKit, just not on the Mac yet.
And, finally, UserNotifications is in the middle there.
That is an example of a framework that we not only brought to the Mac, but we also made public API on the Mac.
And we did that last year during the initial bring up of this technology and we did it on plain sight as well.
And we also unified services and databases, so that a single copy of Photos and Contacts and Preferences serves both AppKit apps and UIKit apps.
And same with Services, there's only a single Copy Paste service single file coordination, and so on.
So this is how the environment for iPad apps for Mac looks.
It's very much like the environment that AppKit apps enjoy and running with native performance characteristics.
Now, before I let go, let me talk a bit about those frameworks about AppKit and UIKit.
Of course, it's not just WebKit and SceneKit.
There are many other frameworks up there.
And I'm showing you two copies of these.
And that's indeed the case.
Since AppKit and UIKit are not unified, the frameworks that depend on them also remain separate even if they are literally called the same thing, like two WebKits, two SceneKits, and so on.
And there are number of reasons for this.
The main one is that classes such as NSView and UIView are distinct and have their own behaviors and support infrastructure.
So, we have distinct declarations and implementations of classes that in turn build upon them.
So, here is declaration of MKMapView for instance for in the case of AppKit and the case of UIKit.
And as you can see these are effectively incompatible definitions.
So, we really do have two copies of these frameworks in the system and also in the developer SDK.
However, it's not something you need to worry about.
The Static Linker and the Dynamic Loader do the right thing when it comes to finding the right copy of these frameworks.
Either at built time during linking or at run time when loading.
So, let me shift gears now and talk about why we're doing this.
Why are we bringing UIKit to the Mac?
Well, I mean this is part of the reason, you know, just showing you of just few of the hundreds of thousands of iPad apps out there that you've created.
And we think many of them would be great on Mac.
And there are also millions of Mac users out there and many of them would look great with your apps.
So this technology provides them with access to these apps and creates new opportunities for you.
Or you may be wondering whether this technology is appropriate for your application.
And that's an excellent question.
So, let's say you have an iPad app and you don't have Mac app and you want to bring the functionality of your app to the Mac.
Well, that's a very good case, very good time to consider this technology.
One case of this is, you may have an iPad app, but maybe on the desktop the experience is a web page.
Now, web interfaces can be pretty great, but they're not native, you know, native apps have menu bars, command keys, access to hardware features, robust local storage, so much more complete experience.
In another case, is you may have an older Mac app, but maybe your iPad app has features you have since added and it's come further, the two have fallen out of sync.
So, this may be a way to freshen your Mac app.
One other case is maybe replacing a Mac app that's using a non-native, non-optimal third party porting framework.
If your iPad app is native, this could be a good way to modernize your Mac app.
But, however, there is one important thing to keep in mind.
If you already have an AppKit app on your Mac on the Mac that is well-maintained and up to date with your iOS version, there is no need to consider this technology, really, you can continue using AppKit.
AppKit is a first-class framework that provides a complete set of APIs for developing Mac apps.
In fact, it provides access to a more complete API set than this technology provides on the Mac.
Now along those lines, there's also some apps that are just not candidates for this technology.
One example is iPhone apps.
iPhone apps are optimized for the smaller screen, so they're trying to take advantage of that small screen.
We really want you to have an iPad app that's taking advantage of larger screen sizes before bringing it to the Mac.
Another case is apps that are built around mobile features.
Earlier I showed you ARKit is not being available.
If your app is based on ARKit, it's not going to run very well on the Mac.
But if the augmented reality functionality is not crucial, it may still make sense to bring the app over and conditionally remove that functionality on the Mac.
So, at this stage, before inviting Jake on stage for his demo, let me mention the high-level goals that help us design and deliver this technology.
We want this to be easy to get started.
We have a check box for that, you saw it yesterday and you'll also see in a minute.
And we want you to be able to work with a single source base.
A single source base enables you to develop without forking your code and enables carrying both the iPad and Mac versions of your app forward simultaneously.
I want you to think of your apps as iPad apps on the inside.
That's the way you've been developing them as iOS SDK and we want you to think continue thinking in terms of the iOS SDK and concepts.
And finally, we want the app to come across as a Mac app on the outside.
So, to the user, it is a first-class Mac experience.
OK. So with this, let me invite Jake on stage to show you how you get started.
[ Applause ]
Good afternoon, everyone.
So, now that you've learned a bit about iPad apps for Mac, I'm going to show you how you can bring your apps to the Mac using Xcode.
Traditionally, you'd have to learn a completely different UI framework and write a whole new app from scratch.
But with Xcode 11, we're making it possible for you to reuse your existing project and source code.
Let's go give it a try.
So, here I've got a small recipe management iPad app that I've prepared earlier.
And to get started, we're going to open our project in Xcode and we're going to check the Mac check box under Deployment Info.
Now, note that this will only be available if your app supports iPad.
So, I'm going to go ahead and click this check box and we're going to see a sheet pop up which will explain that Xcode is going to make some changes to your project.
So, I'm going to go ahead and click Enable.
Now, let's take a look at what that did.
So, one of the first things you'll notice is that there is a new My Mac run destination in the Scheme Selector.
This allows you to build, debug, and test your app for the Mac.
You'll also see that there's a new label below the Bundle Identifier field.
All iPad apps and app extensions brought to the Mac using this technology will automatically get a new bundle identifier by default which uses a special prefix.
If you have any hard-coded references to your app or its app extensions bundle IDs, you may need to make some co-changes to take that into account.
And you can learn more about this and how it affects signing, provisioning and distribution in our next talk, Taking iPad Apps for Mac to the Next Level.
Next, let's talk about capabilities.
On iOS, apps need to specify usage description strings in their Info.plist, in order to gain access to certain protected system resources like the camera or the user's location.
Xcode will use this information to automatically add equivalent entitlements to your Mac app, so that you get the same behavior as you had on iOS.
For example, iOS apps get the ability to make outgoing network connections by default, whereas Mac apps need entitlement.
If we go to the Signing and Capabilities Editor, we can see that Xcode has automatically added the network client entitlement as well as a couple of others based on the Usage Description strings in our apps Info.plist.
Next up are frameworks and app extensions.
While the majority of the iOS frameworks are also supported on macOS, there are still differences between the two SDKs.
I'm going to focus primarily on the Xcode project configuration and later Jason will tell you more about the API differences.
Now, when Xcode updates your project it automatically excludes any unavailable content from your Mac build.
This includes unavailable system SDK frameworks, unavailable app extension types, and Apple Watch content.
If we go back to the general tab you can see in the frameworks libraries and embedded content section that Xcode has already done this for some of our dependencies.
Both ARKit and our Watch app are marked as building for iOS only.
So, let's go ahead and try to build this out for the Mac now.
So, let's see if we've got an error.
And this error says that one of our dependent frameworks is not compatible because it was built for iOS Simulator.
You may be wondering, both iOS Simulator and macOS frameworks are built for x86.
So, can you reuse them in your iPad apps for Mac?
Well, the answer is no.
For any pre-compiled binary libraries that you may have, you'll need to reach out to your vendor to provide a version specifically compiled for the iPad apps for Mac environment.
Frameworks built from source as part of your project on the other hand are automatically configured to build for Mac by default.
You may want to consider using the platform drop-down if you're in the frameworks libraries and embedded content section, to exclude incompatible libraries from your Mac build until you're able to obtain a compatible version or if the functionality that it provides isn't suitable for your Mac app.
However, if you rely on that framework for critical functionality, it may be best to wait for updated libraries from your vendors before reporting to Mac.
Now, in this case, I happen to have an updated copy of this library available.
So, I'm going to go ahead and add this to the project.
So, first I'll delete the existing framework.
And, now, we'll go ahead and drag the new one in.
Now, the first thing you may notice is that this isn't a regular framework.
This updated library has been delivered as an XC framework, which is a new feature in Xcode 11 that allows library developers to package a library from multiple platforms into a single distributable bundle that you can use in your Xcode projects.
XC frameworks are not required when bringing your app to the Mac, but then they got much more convenient to manage your dependencies across multiple platforms.
You can learn more about them in binary frameworks in Swift.
And note that they do work for Objective-C as well.
Next, one of the most important aspects of bringing your app to the Mac is, of course, your code.
Now, I previously showed you how Xcode will automatically exclude some unavailable frameworks from your build.
But you may still need to make adjustments to your source code in order to compile out any references to API as provided by those frameworks which may be unavailable due to differences in hardware or differences in user experience.
You can conditionally compile your code using the target environment platform condition in Swift or the target OS macros in Objective-C.
So, let's take a look at that now.
I'm going to go ahead and try to build again.
And we can see that ARKit is not available.
Great. So, I was hoping to add a way to preview my recipes in augmented reality.
But we can probably get away without that, the food is best experienced in a different kind of AR, actual reality.
So, let's just go ahead and comment that out.
So, I've got some sample code here I can use to do that.
I'm going to go ahead and #ifdef out ARKit.
And I'm going to #ifdef out the corresponding API as well.
OK. Let's try to build it one more time.
OK. So, this time this looks like the StoreKit framework is available in the Mac.
But the specific API that we're trying to use here is not.
Now, I'm not sure what my apps marketing team is trying to do here, but probably not too important.
I'm just going to #if this out as well.
OK. And we can leave it to do for them, TODO: Something else?
So, at this point, I could run the app.
But before I do so, let's consider one key refinement that we can make to our Mac app.
By default, UIKit apps will use the icon from your iPad app, the same rounded rec design, as you can see here, this nice little cookie.
But Mac apps traditionally have beautiful detailed rich icons, which can be up to 512 points in size and make use of transparency for even more design and flexibility.
Customizing your app with a great Mac icon really helps it to standout and you can learn more about how to design a great one in the section, What's New in iOS and macOS Design.
So, to add a Mac specific icon we're going to want to navigate to the Asset Catalog Editor in Xcode, so select my Asset Catalog here and I'm going to select the App Icon Resource.
And I'm going to the Inspector and I'm going to check the Mac check box to reveal the new slots.
And from here, you just need to drag in your new icons.
So, I'm going to go ahead and use an icon set that I've prepared earlier.
I'm going to go ahead and drag that in.
Oops. There we go.
OK. You can see we got this great cookie icon.
So, let's go ahead and give this one more try.
I'm going to go ahead and build again.
And this may take a moment because we've switch from building for iOS to building for the Mac.
It's going to need to rebuild all of our source code and our resources.
I'll give that a moment to come up.
And we have successfully built and run for the Mac.
And you can see we've got oh, thank you.
[ Applause ]
And you can see we've got a title bar, we've got window stop lights, we've got a menu, resizable window, and of course our beautiful Mac cookie icon, just like you'd expect.
And once you're finished bringing your app to the Mac you can click the product archive Menu item in Xcode to create an archive and open the organizer.
And from there, you can distribute to the Mac App Store or do so independently using developer ID.
So, that's how Xcode 11 helps you bring your iPad apps to the Mac.
And now, I'd like to invite Ali back to the stage who's going to tell you more about the user experience improvements that you get for free.
[ Applause ]
OK. So, now, I want to talk to you about things you get for free and I'm not going to talk to you about the lunch you got out on the concourse.
But what you get in your UIKit for Mac app.
So there are ton of frankly there are tons of things you get for free.
Large sections of that whole stack of frameworks, and database, and services I showed you earlier works in your Mac app automatically.
But here, I want to highlight some things that are not just free but also automatically mapped over to Mac paradigms and Mac way of doing things.
So, let's first take a look at that tasty recipe app that Jake used.
So, as you saw on the demo, you got the default menu bar.
The app gets a pretty functional default menu bar that has a lot of menu items that Mac users expect.
Next to get window management.
This includes things like window resizing, full screen, split view, also what we affectionately call the window stoplight.
So there's three buttons in the title bar.
And one more thing to point out, if you happen to have your iPad nearby, you have the ability to display your iPad app for a Mac window on your iPad.
[ Applause ]
Dark mode works automatically.
If you go further and adapt any of the new APIs to make your app a better iOS dark mode app, those will also carry over automatically.
Scrollbars and scrolling also works as expected on the Mac, mapping to overlay scrollbar functionality.
Scrolling also works when the window is inactive which, of course is something that users expect on the Mac with gesture scrolling.
If the user has scrollbars always showing, that will also work automatically in your application.
Now let me talk about settings.
Our recipe app does not have any settings, so I'll show you the vice memos app.
On iOS, apps specify setting bundles and these controls these settings controls appear in the iOS settings app.
For instance, here are the settings for voice memos, in the settings apps.
Now, on the Mac, the design guideline is to access app preferences through a menu item in the app like this.
So, when we see that your app has settings, we give you this menu item and automatically map the settings to a Mac prefpane within the app like so, and you can see them side by side.
So, this is automatic.
[ Applause ]
Your application gets basic support for touch bar, the system touch bar that all apps get.
But in addition, if you're using API such as AVPlayerViewController or UITextView, they will also automatically provide access to the media in the text touch bars in your app, like the ones you see here.
Another key element that's automatically mapped is the Document Picker.
Here is how UIDocumentPickerViewController comes across as NSOpenPanel as the user would expect.
Custom views that you've created come across as is, as intended.
Here in the voice memos app, the custom waveform view looks exactly the same across both platforms.
Now, let me talk about another set of things that come across pretty much as is.
Let's look at a form sheet in News.
Here's News on the iPad and here's the form sheet for managing notifications.
And here's News on the Mac with the same form sheet displayed.
You can see that that form sheet comes across as is along with the UI switches in the content.
Let me show you side by side.
So, here, you're seeing one of my main goals and that's to provide a high degree of source compatibility for your apps where possible.
Trying to give apps full AppKit controls and metrics with represent too much of a disruption.
So, individually, UIKit controls and layouts based on them come across as is providing maximal compatibility for your app.
Now along the same lines, text sizes.
On iOS, the base line font size for controls is 17 points while on the Mac, it's 13 points.
And as you can see, not the same size when displayed next to each other, so two reasons for this discrepancy is the higher relative display density of iOS devices and the need to accommodate touches.
So, to provide interaction consistent with Mac applications, we scale content areas down to 77%.
So, everything in the window is scaled uniformly and you don't have to redesign any of your windows for the Mac.
We have a Font Management and Text Scaling talk later in the week which will cover this and some related topics in more depth.
Now, let me talk about a few more things quickly that you get for free.
If you implement copy and paste, drag and drop, printing or take advantage of the new multiple window, multitasking APIs in iOS 13, these will carry over to the Mac free and automatically.
On the Mac, the lifecycle of your app adjusts to the Mac paradigms and any call backs you implement for managing a lifecycle will also carry over and work automatically on the Mac.
You will hear more about this in our Taking iPad Apps for Mac to the Next Level talk.
Beyond these things you get for free, there are things you can do to make your app a better Mac app and here are some of these.
Jake already covered the Mac icon.
The rest we'll be covering in our advanced session later in the week and also in the iOS and macOS design session later this afternoon.
OK, so thank you.
At this point, I'd like to invite Jason on stage.
[ Applause ]
All right, thanks Ali.
So, I'd like to dive into some of the API differences that you're likely to encounter when you bring your iPad up to the Mac.
And there are three categories of API differences I want to talk about.
Those APIs that have identical behavior and the good news is the majority of the APIs worked as expected.
Those APIs that are mapped to macOS functionally functionality automatically.
And these utilize the iOS APIs but they result in macOS behavior.
And then, finally, APIs that are unavailable for various reasons which we'll get into.
Now, we're not going to cover anything in the first section and Ali covered many of the items in the second section.
But there's one additional area that I like to talk about before we jump into the third section and that is mouse and touch events.
So, iOS is built around a direct, multi-touch interaction model.
And macOS is built around an indirect cursor-based interaction model.
And there are significant challenges when trying to bring a multi-touch application to the Mac and make it feel at home, though we do try to map automatically as much behavior as we possibly can.
We introduced a new UI Hover Gesture Recognizer to let you know when the mouse cursor is position over your views.
And left mouse button drags are mapped to a single synthesized touch sequence that is automatically recognized by tap, psn and long-press gesture recognizers that are set to recognize a single touch.
Standard system gestures are recognized at the hardware or driver-level on the Mac, and they post high level gesture events to the system.
When the UIKit application receives a high-level pinch rotate gesture, we synthesize a pair of touches and deliver them to the view that's under the cursor and this will automatically trigger any pinch or rotation gesture recognizers in your application.
If the user performs the standard system scroll gesture, in this case we don't synthesize any touches but UIKit will automatically scroll in the UI Scroll Views that are under the cursor.
Now, one thing we can't map automatically is custom multi-touch behavior.
Whether you're dealing with the UI touches directly or you've written a custom gesture recognizer, there's simply no automatic way to map from all of the various input devices on the Mac to your custom gestures.
If you rely on this in your application, you'll need to provide an alternate way for the user to accomplish the same thing when you bring your application to the Mac.
So, let's move on to that third category of API differences and that's APIs that are unavailable.
This fall into four general groups, frameworks that are deprecated, frameworks that are unavailable because they're tied to functionality in iOS that doesn't exist in macOS, frameworks that are tied to specific hardware functionality or sensors that don't exist on the Mac.
And, finally, there are number of frameworks that have different behaviors or APIs that are unavailable on macOS for various reasons.
These would be annotated to make this clear and to generate an error in Xcode.
So, let's delve into this a little bit deeper.
Deprecated frameworks are often available for quite some time after they've been deprecated.
However, this is a new platform for your iPad apps.
And so, you shouldn't assume that any of the deprecated frameworks will be available to you.
Now is a great time to migrate off these deprecated frameworks and on to the replacement.
This will not only allow you to bring your iPad application to the Mac, but your iPad app will benefit as well.
There are also several frameworks that are tied to functionality in iOS that does currently exist on the Mac.
The ClassKit framework is designed to allow your application to work with the Schoolwork app.
But this application doesn't exist on the Mac, so it wouldn't make sense.
And HealthKit and HomeKit are not available at this point since not all of the underlying functionality is present.
There are several frameworks that are tied to specific sensors on iOS devices for functionality that can only exist there.
This will not be available on the Mac.
So, if your application uses this, you'll need to conditionalize their use before you can bring it over.
Now, some of the frameworks that are tied to specific hardware on iOS devices do make sense on the Mac.
But the availability and functionality of these APIs will be somewhat limited because Macs often don't have comparable sensors.
In some cases, it's true on non-cellular iPads as well.
So, your app may already be doing the right thing.
To give you a sense of the kind of differences you can expect.
Core Location works but Macs don't have GPS chips.
And so, you should expect them to be less sensitive to changes in location when they're moved.
And if you use Core Motion to control game play in your app, you should be aware that the Mac doesn't have the sensors necessarily to do this nor it would be a very good user experience.
And so, you should add an alternate mechanism to control your game on the Mac.
There are several media related frameworks that have differences you should be aware of.
The Media Player framework gives you basically the same functionality it does on the Mac with access to the Now Playing Info Center and Remote Command Center.
But there's no library access or playback support.
And if you were using the AVFoundation framework to capture still images or video on iOS devices, you can use the UIImagePickerController in UIKit to capture them from the built-in front-facing Mac camera.
A number of other frameworks have differences as well and I want to draw your attention to a couple of them.
So, Metal is largely the same across all of our platforms, so most of you will find that your iPad Metal apps work without change when you bring them to the Mac.
For those of you that are using some of the more advanced features in our latest GPUs such as Memoryless Textures.
We've introduced a new GPU family API that will help you to conditionalize your code to run across a range of GPU families.
And in UIKit, UIWebView will not be present on the Mac.
And so, if you have it already, now is a great time to migrate to WKWebView.
So, as you've seen there's a number of differences in our API and we don't have time to cover all of them.
So, I want to take a moment to talk about how you could determine for yourselves what API is and is not available to you when you bring your iPad apps to the Mac.
So, iPad apps for the Mac are built against the macOS SDK.
And so, for frameworks that are unavailable, they simply are just not present in the SDK.
And for frameworks that have differences between iOS and macOS, we annotate methods as appropriate to make that clear.
We annotate our APIs with @available in Swift and API available in Objective-C.
And for iOS applications, we're obviously only concerned with this part.
And the good news is that availability for iOS automatically implies availability for iPad apps for Mac.
As I've mentioned earlier, the vast majority of APIs are available, so this is typically what you'll see when you look through the APIs.
When there are differences in availability, you'll see that clearly annotated as well.
Here's an example of an API that only exist for iPad apps on the Mac.
Now, API such as this, are fairly rare.
Most of the API differences you'll find for iPad apps for Mac are for differences where the API is available on iOS but not for the Mac.
In the most cases, you'll see the API clearly annotated as unavailable for UIKitForMac.
Ideally, most of your code will be identical when you bring it to the Mac.
However, if you have code that shouldn't be included on the Mac, you can use the targetEnvironment conditional to exclude it.
And if using Objective-C, you can use the Target OS UIKitForMac, target conditional to do the same thing.
Of course, you can use this target conditional to include code which only relevant to Mac.
Data protection is an iOS feature that you use to secure your app's files and prevent unauthorized access to them.
You can read and write your files normally, but the system encrypts and decrypts them automatically.
This is access by specifying one of the following four writing options when writing files to the file system.
On macOS, these data protection APIs are not currently functional.
If you try to use them like in this example, the code will compile and execute but the data is not being stored securely on the file system.
If you need to store data securely, there are several options available to you.
Passwords and related data can be stored in the Keychain and FileVault will encrypt all of the files on the disk transparently, but if that's not sufficient for your needs.
You can use the new AES.GCM encryption API in CryptoKit to encrypt your content before writing it to disk.
As you can see in the short code sample, this API makes it very straightforward to encrypt your data.
You then just need to store the data on the disk and write the key to the Keychain and you refer to the documentation for all the details on how to store and later decrypt the data.
Another difference I want to talk about is your application's Bundle Format.
Application bundles on iOS are considered flat bundles.
When Xcode builds your application for iPad for the Mac, it will build a macOS style bundle that is deeper than the flat bundle format that you used on iOS.
If you're using the NSBundle APIs to find resources in your application, then all of this will be transparent to you.
However, if you've hard-coded paths relative your app bundle, you'll need to modify that code to deal with the macOS bundle format.
iOS supports a wide variety of extensions but not all of them will be available when you work will work when you bring your iPad app to the Mac.
So, here are set of extensions which are supported but you may find some API differences.
These extensions will automatically work with both AppKit and UIKit Macs apps on the Mac.
So, for example, a Share Extension in your application will appear in the Share menu right alongside the Share Extension in an AppKit application.
There are also a number of ACPI extension or sorry, number of extensions that do not currently work on macOS.
Many of this, do not make sense on macOS today like Sticker Packs, Custom Keyboards or iMessage extensions because the corresponding functionality doesn't exist on macOS and in some cases such as the File Provider, you should switch to the macOS File Provider extension directly.
So, we've seen a number of API differences that will impact your iPad apps for Mac.
Let's take a look at the demo of how you can start to deal with some of these differences in your application.
So, our recipe application has the ability to mark a recipe as a favorite and you can see one of the recipes already has a heart next to it, to show the state.
Now the app has a custom multi-touch gesture that will toggle the favorite state.
But as we discussed that won't work on the Mac.
So, let's add a custom menu item to do that instead.
So, first thing we need to do is disable our Custom Gesture Recognizer.
We'll do that by wrapping it with the target conditional that we talked about before.
Hang on one second.
OK. And then, the next thing we need to do is take the method that that Gesture Recognizer calls which is toggleSelectedRecipe FavoriteState and mark it with the IBAction annotation.
This is so IB or the IB can see this.
And then, finally, we need to add a Menu Validation method, and this will toggle the menu item between remove favorite and make favorite based on whether the currently selective recipe is favorite.
Now, we just need to add our custom menu.
So, we'll go to the Storyboard Editor and we'll drag out the main menu.
Oops, sorry, I dragged the wrong thing.
We want to add a new menu item to the file menu.
So, I'll add an inline menu section.
We only need one of these items here.
So, we'll delete the other one.
We'll change this to Make Favorite.
We'll give this a command key equivalent.
And then all we need to do is wire that up to the first responder.
And have it send that same method that our Gesture Recognizer would send.
So, now, let's build and run our application.
I think that was in the wrong place.
So, now, you see we have a new menu item called Make Favorite and when I click that we see the Favorite icon and of course remove the changes removed Favorite Network as well and we'll just test our menu short clicking shortcut and of course that works as well.
[ Applause ]
So, you've just seen how easy it is to bring your iPad apps to the Mac.
So, if your app's a good candidate, then check the box and get your app building and running on the Mac.
As always consult the docs and release notes for the latest information and we'll be in the labs right after this session to help you out and please join us on Thursday afternoon at Taking iPad Apps for Mac to the next level.
We we'll cover how you can make your app feel even more at home on the Mac by incorporating platforms specific features.
Please check out the, What's New in iOS and macOS Design session later today where we'll discuss design considerations when bringing your iPad app to the Mac, and finally, the Font Management and Text Scaling session on Thursday morning.
We'll go into detail about how new fonts are handled or how fonts are handled in iPad apps for Mac.
Thanks. Enjoy the rest of the show.
[ Applause ]