WWDC2019 Session 205

Transcript

[ Music ]
[ Applause ]
>> Thank you.
[ 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.
Another error.
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?
OK. Great.
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.
Good afternoon.
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.
Oops, that.
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.
Main menu.
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 ]