WWDC2016 Session 207

Transcript

X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
[ Music ]
[ Applause ]
>> Thank you.
Hello, and welcome.
My name is Tony Parker.
I am the manager of the
Foundation team at Apple,
and I'm here with my
colleague Michael LeHew to talk
about what's new in
Foundation for Swift.
This year the Foundation
team has put a lot of effort
into improving the way
that you use the Cocoa
and Cocoa Touch APIs in Swift.
We started by working on the
Swift API Design Guidelines.
After that, we looked at how
all of the Objective-C code
that the Cocoa SDK uses and your
own code is imported into Swift,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that the Cocoa SDK uses and your
own code is imported into Swift,
but we knew that we
could go further.
So, we have introduced a
brand new set of value types
in Foundation, and
along with that a ton
of new Swift-specific API.
So, let's go ahead and jump
into design guidelines.
Now, this year we're
working on Swift 3, and yet,
from the beginning our goals for
Swift have remained the same.
We want you to write code that's
fast, safe, and expressive.
We've built the libraries,
the standard library,
and the language
around these core ideas.
And many of you have also
internalized those same
principals and built your
application around that.
However, we all know that there
is another part to that story,
and that it the Cocoa SDK.
Your app depends on this just as
much, or maybe even more than,
the Swift standard library.
It needs to feel like it's
part of the same ecosystem.
Because the SDK is a
critical part of that story
about how we develop apps on our
platforms, it's really important
that the language and the
libraries work together.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So this year we focused on
this idea of expressiveness.
When I say expressive,
I actually mean it
in two different ways.
First is your ability as app
authors to write Swift code
that expresses your intent to
the compiler and the libraries,
but it goes the other way too.
The libraries need to be
able to express their intent,
their design patterns and
their ideas about how best
to use the API to
you as an app author.
And so, while working
on the guidelines,
we focused on this idea of
a consistent experience.
Every decision made about those
guidelines was done in support
of the idea that the language
and the libraries
don't stand alone.
They have to work together.
So, for example,
from the libraries,
they bring a huge
number of features.
Many of the features that
you see in the new versions
of our platforms this year
are based on new features
in the libraries that you
can also adopt in your apps
to improve your experience.
These libraries have a
widespread adoption across all
of our platforms, including
this year new, Swift Auto ARC
and Swift Open Source.
So, we have Swift
core libs foundation
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
So, we have Swift
core libs foundation
which is bringing the
Foundation API, much of it,
to other platforms like Linux.
These libraries have a
battle-tested implementation.
Many of them have been
around since the beginning
of OS X or even further back.
They also bring with them,
thanks to the Cocoa
naming guidelines,
a consistent set of conventions.
This means that when you
see a new piece of API,
you can understand how it works
and what it does
almost immediately.
And finally and importantly,
these libraries are
under continuous and
active development.
Not only are we adding
those new features,
but we're making enhancements,
fixing bugs, and more,
and we're going to continue
to do that every year
as we release new OSs.
Now, on the other hand,
the language, Swift,
brings with it things that we
just didn't have in Objective-C.
For example, first class
abort for generics,
and built in support for
mutation, which is a key part
of Swift's story about safety.
There's also things like
protocol extensions,
function overloading, and
default argument values,
all of which make
a dramatic impact
on how you design
your API in Swift.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
on how you design
your API in Swift.
This isn't a complete
list on either side,
by the way I just
ran out of space.
There's plenty more
to go around.
So, we came up with
three key documents.
The first was SE-0023,
the API Design Guidelines.
Now, all these documents
were sent
to the Swift Evolution
mailing list, which gives you
and the rest of the
Swift community a chance
to participate in the design
and evolution of the language.
Now, we see these guidelines as
a unifying document for current
and future Swift libraries.
Along with that we have SE-0006,
which applied those design
guidelines to Standard Library,
giving us a consistent and
predicable set of primitives
that we can build on
top of, and SE-0005,
which dramatically improved the
expressivity of the Cocoa SDK,
by doing things like
adding default arguments,
improving option sets
and building properties,
even automatically adopting
protocols in some cases.
We had a whole talk about this
that I definitely recommend
that you check out if you missed
it, Swift API Design Guidelines.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, all these were
tremendous advances,
but we knew that we
could go even further.
That's because Swift goals
go beyond just the names.
Mutability in particular is
a key part of the language,
and so, we turned our
attention to Foundation.
Now, if you're wondering
why Foundation?
The answer is because
it's kind of special,
and I'm not just saying
that because I work on it.
Foundation occupies a
unique spot in the SDK.
What's interesting about it
is that it's low enough level
to be used everywhere, on all
those platforms I mentioned.
Yet, at the same time,
it's also high enough level
to establish a whole new set of
common types and design patterns
that again you see reflected
throughout the entire SDK.
If we go back to our picture
from earlier and sort of zoom
in on the Cocoa SDK, you'll see
lots of frameworks that you use
in your apps every day, from
UIKit to SpriteKit, and WatchKit
to CoreData, and many
other cores and kits
that don't fit here either.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, what's interesting
here is that almost all
of these are built
on top of Foundation.
So, we see Foundation
as a leverage point.
What that means is that we can
make a small set of changes
in Foundation, and that can have
a big impact on the entire SDK.
Partly, that's because
Foundation is the home
of many value types.
So, we focused on this idea
of evolution over revolution.
We've seen everything
that those libraries bring
to the development of your apps.
We're not going to
throw all that away
because we have a new language.
Instead what we're doing is
we're bringing the language
and the libraries
closer together
by making incremental
improvements to both.
The changes that we're talking
about today are a
continuation of that process.
And so with that in mind,
the Foundation team put forth
two additional proposals
to the Swift Evolution
mailing list.
The first was mutability
in Foundation value types,
which is about embracing
that Swift mutability model
in the Foundation framework.
And also, dropping the NS
prefix in Swift Foundation,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And also, dropping the NS
prefix in Swift Foundation,
which is about establishing
those common types
and design patterns for Swift,
no matter which platform
you're using.
So here is an overview of some
of the API improvements
we've made this year.
First and foremost, value
semantics, a brand new set
of value types that you're
going to see across the SDK.
Beyond that, we did
an additional set
of naming improvements,
beyond what the Objective-C
translation into Swift can do.
We've adopted many
standard library protocols
on these types, which means
that your generic
algorithms can now work
on Foundation types as well.
We've added additional
type safety and a lot
of new Swift-specific features.
So, let's do a quick
overview of value types.
Now, value types
are distinguished
from reference types, primarily
based on their behavior
around copying, so value types
copy their content on assignment
or passed as a parameter.
Here's a quick example.
I've got a point.
I use the equals operator
to assign that point
to another point, and when
I mutate that second point,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to another point, and when
I mutate that second point,
you see that only
the copy is mutated.
I didn't affect the
content of both.
That's because CGPoint
is a value type.
Now, on the other hand,
reference types share
their content by default.
Here I'm going to create some
data using the reference type
and its mutable data.
Then I use that same
equal operator to assign
that data to otherData.
However, this time, when
I mutate that second data,
you can see that it
affects the content of both.
Now, it's important to
understand that neither
of these is better
than the other.
You just use them
in different ways.
I like to think of it as a
couple of tools in the tool box
that you can reach for when
you have a particular problem
to solve.
So, when you're trying
to decide for yourself
if your type is a value
type or a reference type,
you should think about object
identity and stored contents.
Let me explain by way
of a couple of examples.
So, in Foundation, we
have a class called.
OperationQueue has a singleton,
called the main operation queue.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
OperationQueue has a singleton,
called the main operation queue.
That operation queue,
the main operation queue,
is where you put
work that you want
to happen on the main thread.
And so, there's only
one of them.
It has a kind of identity.
If I were to copy the main
OperationQueue then it would no
longer be the main
operation queue.
So, we believe
that OperationQueue
is a reference type.
Another example, a pattern
that you see throughout the
Cocoa SDKs is a delegation.
So here is the delegate,
or one of the delegates
for URL session,
and you'll notice
that the delegate protocol
has an argument, right there,
called Session, and that
tells the object that's being
delegated to which URLSession
it's doing work on behalf of,
and that idea of which
URLSession it is implies,
again, identity.
So, we believe that types
with delegates are
usually reference types.
On the other hand,
many types are more
about their store contents.
For example, Date.
This is one of our new
Foundation value types.
Date is an absolute
point in time.
We can have two Dates
that have the same value,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
We can have two Dates
that have the same value,
the same absolute point in time,
and be talking about
the same Date.
We don't need to talk about the
reference to that point in time.
In fact, if we look inside
the implementation of Date,
as you see here, it's
actually just a double,
and a double is something
that we sort
of already intuitively
understand as a value type.
Another example is Data.
Data is another one of our
new Foundation value types.
Data, normally you care about
the contents of that Data,
the bytes that are there, not
the actual NSData instance.
So, Foundation has made
Data into a value type.
Now, copying the data
every time that we pass it
as a parameter would
quickly get very expensive.
So, we performed an optimization
called Copy on Write.
So, here I'm going
to create some data,
and you see I've got a
struct, but inside that struct,
I also have a reference.
So, another example of
things working better
when they work together.
Here I'm using both a
reference and a value
to get the performance
characteristics
that I want along with the value
semantics that are important.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
Now, if I use that equal
operator to assign that data
to another data,
then you can see
that I've got another
struct, but it points
at the same class
under the hood.
However, if I mutate that Data,
then we will copy the Data,
mutate the copy, and now we've
got two independent Datas.
If I continue to
mutate the second Data,
we can tell that that Data
is uniquely referenced,
and we don't need to
copy it each time.
So, this is an extension, or
actually, just another use
of the same technique that
we've talked about in the past,
including last year,
with building better apps
and value types in Swift.
So, check that out if you
want some more information
on how this works.
So, we did a survey of
every API in Foundation,
and we came up with
this list of things
that we think would
make great value types,
and I think you'll be happy
to see many of the types
that you use every
day on this list.
That includes Data and
Date, as I mentioned,
but also other types that
are really popular like URL,
IndexPath, CharacterSet,
and a lot more.
And many of these types not
only became value types,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And many of these types not
only became value types,
but gained a lot of
great new API as well.
Now, to give you an idea
of what that looks like,
I'd like to invite
Michael on stage.
[ Applause ]
>> Thank you, Tony.
Let's start by visiting
the new homes of many
of Foundation's enumerations.
Now, as you know,
Objective-C enumerations
and option sets live in
the global namespace,
alongside the types
that consume them.
For example, NSNumberFormatter
alone defines four enumerations
for the style, behavior, pad
position, and rounding mode.
And each of these are implicitly
associated with NumberFormatter
through careful and
consistent naming convention.
In Swift 2 as you
know, these important
to the global namespace as well.
But that doesn't feel
like native Swift.
Swift supports nested types,
and so in Swift 3 we made the
decision to relocate these types
to be declared inside,
where they're destined to.
So NumberFormatter now has
internal types of style,
behavior, pad position,
and rounding mode.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
behavior, pad position,
and rounding mode.
And their names are
no longer redundant,
and this greatly reduces
the number of types
that Foundation declares
in the top-level namespace,
and now the relationship
is explicit,
our APIs more expressive
and more discoverable.
Sticking with the
theme of enumerations,
many Foundation APIs also use
families of streamed constants.
Examples include notification
names, URL resource keys.
Now of course, Swift has support
for enumerations that rely
on raw representations
that are other
than integers, including string.
Wouldn't it be great if
we could do the same thing
in Objective-C?
Well, new this year we can, and
the constants are now defined
in terms of very specific
kinds of string constants,
like notification name
and URL resource key,
and many, many more.
And these constants remain
extensible, in Objective-C
and also in Swift, where we can
also see that we nest them just
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and also in Swift, where we can
also see that we nest them just
like their integral
cousins, so that using them
in Swift 3 is both
natural and expressive.
Now another common Foundation
design pattern is associating
state with a type.
For instance, the
standardUserDefaults.
Now, of course, Swift support
for class properties are
a great fit for this idea,
and new in this year, we
have brought class properties
to Objective-C, and
they're declared just
like instance properties,
except we now accept
this fancy class keyword,
and because we know that
it's a class property,
we no longer need to
import it as a func
as we did in Swift 2.2.
It can now appear as a class
property, just as you would
if you were defining
this natively in Swift.
But we didn't stop there.
There's some redundant
words here, and in Swift 3,
we overhauled the way that
Swift code is manifested,
or Objective-C code
is manifest in Swift,
so that our final API could
look a little more like this.
We know it's our user defaults,
and by helping Foundation grow
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
We know it's our user defaults,
and by helping Foundation grow
to be more Swift-like, we've
achieved great benefits
for both Objective-C and Swift.
Now Tony mentioned many
Foundation types deserve
to be value types, and so I'm
going to talk about a few.
We'll start with Date.
Now let's suppose we want
to schedule a reminder
for when we should go home.
We'll start with Swift 2.2,
just to motivate our example.
Let's suppose that we have
a function that can answer
when we need to go home, and we
call it, and five minutes seems
like a good time for our
reminder, so we'll go ahead and,
you know, offset
that a little bit.
Now, it's worth pointing
out, NSDate is
and remains a reference type,
and so there's actually two,
potentially two dynamic
allocations going on here.
One here, and another here.
Now in Swift 3, we gain
access to the Date value type.
So, let's go ahead and use it,
and consuming it
is very similar,
however now this var takes on
a whole new kind of behavior.
We specifically, we now
allow inline mutation.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
And so, we've done zero,
these two examples here are
doing the exact same thing,
except with the value
type we've done no extra
dynamic allocations.
Let's continue our example.
Now, of course, we can
do this inline as well.
Now, with reminders, it's
only really meaningful
to schedule them if
they haven't happened,
and one of the great
things that Swift brings
to the table is automatic
conformance to protocols
when you satisfy certain
criteria, and so in this case,
Date Auto has conforms
to comparable,
which gives us access
to the less
than operator, which we use now.
And we can go ahead
and schedule our timer,
but first we need to create it.
And so we'll use another new
Foundation API this year,
which is this fancy
closure-based timer API,
where we initialize the
timer with a closure.
So no more selectors
and targets there,
and we'll schedule it
on our main run loop.
[ Applause ]
I'll also call out thread
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
I'll also call out thread
and run loop have those
as well I believe.
And we schedule them on our
main run loop and we're done.
And this is a great
example of how all
of these familiar Foundation
APIs really can come
across so beautifully
in Swift 3.
This is some of the most
Foundationy code I could
possibly have in a demo.
I have a run loop, I have
a timer and some dates.
I just, there's only
a few other things,
and this is pretty
much all of Foundation.
And there isn't a
square bracket in sight.
So, another new example,
or another new type
in Foundation is the
measurement value type.
And let's suppose with
a new example here,
we care about how
long our commute is,
and we're lucky enough to
live two short streets away
from where we work.
Now, measurements
are value types,
and Swift supports
operator overloading,
and not only are they
value types, though.
They're mathematical in
nature, and so it makes sense
to specify operators on them.
No one will look the other
way, or make a sour face
if we contemplate
adding them together,
and so we can compute their sum,
and we can even convert them
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and so we can compute their sum,
and we can even convert them
to a different kind of unit.
And let's suppose we were
curious how long it took
for us to get to work.
Well, we could do that as
well, except in Swift 3,
if we were to try to build
this code, it would fail,
and it would fail at
compile time because,
thanks to the power of Swift 3's
generics in type constraints,
we actually have designed this
in a way that the difference
in units is knowable
at compile time,
and so the Swift compiler
can detect us and tell us
that we're trying to do
an invalid conversion.
To learn more about
measurement and units
and the whole new
ecosystem of types
that we've introduced this year,
be sure to check out this talk
on Friday afternoon
to learn more
about measurements and units.
I'm going to switch
to another example.
I did say this was going
to be an adventure.
Suppose we want to
buy some MacBooks.
We'll use the new URL
Component's value type
and we can do this
very expressively.
We'll begin by describing
mutable components,
which we'll use as
a template below.
And we iterate through
the products that we want
to purchase, make a copy of
our template, and then mutate
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
to purchase, make a copy of
our template, and then mutate
that copy, specifying the
product that we wish to buy.
Note that we're safe
to explicitly unwrap
this optional here,
because we specified that it was
non-nill in our template above.
We can go ahead and
print our URLs and we see
that we have been able to build,
you know, the URLs that we'd
like to purchase with no
memory management whatsoever.
All we had to do was
declare our intent, whether
or not something was mutable or
not, and the language took care
of the rest of the
details for us.
Now, another thing
that Swift 3 brings,
or Swift in general brings
to the table is protocol
components.
In many Foundation
types, like Date,
getting useful new capabilities
thanks to new conformances.
For instance, CharacterSet
and IndexSet are now
conformed to SetAlgebra.
So you can union, intersect, and
symmetric difference these guys
to your hearts' content.
Data is also now a
MutableCollection,
MutableRandomAccessCollection
of unsigned eight-bit integers,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
MutableRandomAccessCollection
of unsigned eight-bit integers,
but, like you always
thought it was.
Let's look at some of the
things we can do with some
of Data's new conformances.
First we're going to need
some data, and I happen
to have some base64
data lying around,
which we'll parse using
the normal initializer.
In the explicit unwrap here
is, I know it's safe to do this
because this is a demo,
and I know that that's
valid base64 [laughter].
You should probably use a
try there if you do this
for yourself, but let's say,
you know, I like statistics
and the nice thing to look
at when you have
statistics is a histogram.
That's always a good
thing to start.
So we're going to
build a histogram.
We'll use as our
backing storage,
we'll use a native Swift array,
which will initialize to zero,
and we'll just use the byte
value of each byte in the data
as the index and maintain
a frequency count.
So let's, because Data
is a collection iterating
through its bytes, is natural
and expressive, which we can do
with a four N loop, and so
we'll produce our histogram.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
with a four N loop, and so
we'll produce our histogram.
And let's take a look.
Well that definitely
looks like a histogram,
and like all histograms,
there's signal and noise,
and I'm seeing a lot of high
frequency data in there,
and I'd like to filter that out,
and luckily Data's a collection
now, and so we gain access
to things like Map,
Reduce, and Filter,
and all of your other
favorite collection functions.
And so, let's say we wanted
to remove all the data
that was greater than three.
It's as simple as
specifying a predicate now,
and we can generate
our new filtered data.
And also as a collection,
Data is sliceable,
and these slices work just
like the mutable collections,
or value type collections
that you're already
accustomed to in Swift.
Mutating them invokes the
same copy on write machinery
that Tony described earlier and
they work just the same way.
Now, Data also remains
extensible through inheritance
of the underlying
reference type,
and that's a very big sentence,
so I'll walk through an example
to show what I mean by that.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
As an example, let's go ahead
and create a custom
NSData subclass
that allocates no storage,
but represents a virtual
collection of all ones.
We'll call it an AllOnesData.
Very descriptive.
And I'm only going to show the
implementation a single method
here, specifically
getBytes, wherein the promise
of this class is more
or less fulfilled.
We set all the bytes to one.
So we don't need to store
anything, and let's go ahead
and create a read-only
instance of this.
But we won't just
use the reference.
We're actually going
to create a value type
that wraps the reference
type here.
And using that, we just use
the new initializer for Data,
and it works exactly the
way you would expect.
We have a ones value type that's
now pointing to the reference
of all ones, and those
ones are virtual.
They don't actually consume
bytes in memory currently.
Let's go ahead and create
a mutable copy, and again,
we've not done any mutation,
so we don't need to allocate
or manifest any of those
bytes in memory currently.
But let's get ready to mutate
those bytes, and to do that,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
But let's get ready to mutate
those bytes, and to do that,
we're going to actually use
another new Foundation API this
year, which is the
Scoped Pointer Accessor,
called withUnsafe MutableBytes.
And this is much better than
just calling mutable bytes
on the data itself, because
we're scoping the access
to those bytes within the
closure that we're specifying,
which it makes it very easy to
reason about where, you know,
you don't have pointers
just flying around.
Pointers are only going to
be in these little accessors.
And so we actually perform our
mutation, invoking the copy
on right machinery, and
those bytes are now,
the copies bytes are now
manifested memory for reals.
Let's move on to
another example.
I'm tired of talking about Data.
Let's talk about, URLs
and URL properties.
Now to motivate this
example, I want to talk first
about how we did
this in Swift 2.2.
So in Swift 2.2, we would
ask for a NSURL file URL,
we're going to talk about by
special file, and this file is
so special, I keep it at
the root of my file system.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
so special, I keep it at
the root of my file system.
And I'm curious about
three properties.
I care about the creation date,
whether or not it's regular,
and for some reason, the
maximum file size for the volume
that this file's located on.
And these are just strings
in Swift 2.2 and you just,
this is just an array
of strings.
And when I ask my URL
for its resource values,
I just get a regular dictionary,
and there's no type information.
It's just a string to an
object, which means consuming
that result requires a lot of
as is typing, and so I have to,
you know, suggest
that it's a Boolean,
and suggest that
it's an integer,
and I'm constantly consulting
the references to make sure
that I'm getting it right, and
further, mutation is also just
in terms of the dictionary.
And so you can do
absurd things like this,
and it's every failure is
going to a runtime failure.
So, let's see how this
gets better in Swift 3.
In Swift 3, creating
the URL is similar,
but we no longer use a
class factory method.
This is moved into a
regular initializer syntax.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
This is moved into a
regular initializer syntax.
We're still talking
about my special file,
and instead of asking with an
array of strings we're going
to use those new strongly
typed string enumerations
that I mentioned earlier, and
we'll produce a set of them,
and when we ask the URL
for the resource values,
no longer are we going
to get a dictionary,
but instead we're
going to get a value,
a new Foundation value
type, and let's see what
that Foundation value type
is for the three properties
that we're asking
about right now.
As you can see, creation
date is a Date,
its regular file is a Bool,
and volume maximum file
size is an integer.
And it's also worth pointing
out that the URLResourceValue
struct itself is lazy.
It's still implemented in terms
of the dictionary that was done
in the Swift 2 API, so we're not
necessarily this giant struct
of things that are
going to consume memory.
It's still going to be,
I asked for three things,
I get potentially
three things back.
And further, if you
have custom keys,
the dictionary is still here,
but no longer are you going
to ask for a string,
you're going to ask
for the URL resource key
that you're interested in.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
for the URL resource key
that you're interested in.
Now, you might be noticing
there's a lot of question marks
and the reason why is, well,
there's two reasons why.
The first is that you
didn't ask for it.
So, if you didn't ask for the
creation date it won't be there,
and that again, goes back to
that sparseness of the data.
The second reason why
it might not be there is
that the property itself might
be failable, and as an example
of VolumeMaximumFileSize.
Let's look at two
examples of how that works.
So because we asked for regular
file, we're entirely justified
to explicitly unwrap
our optional here.
It will be there.
We asked for it.
However, the documentation
for VolumeMaximumFileSize says
that not all volumes and not all
file systems support a maximum
file system size, and so
it might not be there.
And as a perfect example of a
time to use the if let construct
in Swift, to conditionally
set that local variable.
Now, let's talk about mutation.
Of course, the mutation
API now for the URLs
in URLResourceValues is in
terms of its new value type,
and so when you try
to, you know,
even though this is my special
file, and I'm trying very hard
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
even though this is my special
file, and I'm trying very hard
to say that it's not regular,
the compiler will catch me
at compile time instead
of letting me discover
that problem at run time.
And further, the creation date
is strongly typed as a Date,
and so something absurd
like this might work
with Siri, can't work with code.
Now the last thing
I want to talk
about on this Foundation
adventure is I want to talk
about Swift's native
enumerations.
And we're going to talk about
data again one more time,
because there's a
really good example.
When data takes ownership
of an UnsafeMutablePointer,
you have the option of
specifying a deallocator.
Data supports many
of these by default,
and including the option to
specify a custom deallocator.
Now, Swift supports
associated values with enums
and oftentimes you'll
see these with, you know,
integers where you can do case
expressions and stuff like that
to be able to, you know, do
really cool pattern matching
with it, but here
we're taking a closure,
because we actually want
to wrap the behavior
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
because we actually want
to wrap the behavior
that you want to provide.
Let's see this in action.
We'll start simple
with a malloc case.
Of course, you can
still malloc in Swift,
although you probably don't
see it in a slide very often.
So, you malloc, and when you
hand this pointer off to Data,
you can, you'll deallocate
it with free,
and the syntax there
is just simple
as using the integration
values themselves.
Let's look at a custom example.
Let's suppose we have a
function that allows us
to create glorious pointers,
which we want to make sure we
that we free gloriously,
lest they be offended,
and so we can specify the custom
deallocator, it's as simple
as providing a closure
and making sure
that you do the custom
thing that you like to do.
And this is really powerful, and
really powerful concept or idea
for framework developers,
because in other languages
we would have needed
to provide a second
function pointer-based API,
but now in Swift 3, we can
provide a single enum-based API
that expresses all of
these ideas very cleanly,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that expresses all of
these ideas very cleanly,
and expressively.
And so that concludes our
API adventure for now.
Hopefully we saw a great
many wonders, and I'm going
to hand things back to Tony
to talk a little
more about adoption.
[ Applause ]
>> Thanks Michael.
All right, now you've seen just
a little bit of what's possible.
Let's talk about how you
can use it in your app.
First, let's talk
about bridging.
So, keeping with this theme
of iterative improvement,
we've extended the
exact same concept
that you're already familiar
with from Swift 2 for bridging
between Objective-C and Swift,
so if you understand how String
and NSString are
bridged, we've extended
that exact same concepts
for Data and NSData
and all the other value
types that you see here.
That means that all
of the imported API
from Cocoa SDK is going to
use these new value types,
and that's a key part of how we
achieve this idea of leverage.
So for example, in
AppKit in Swift 2.2,
you'll see this class called
NSDatePicker, which let's,
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
you'll see this class called
NSDatePicker, which let's,
presents a UI to allow your
user to pick a date and it has,
among others, two properties
for controlling those dates
and you see here their
marked as @NSCopying,
and also NSDate reference types.
In Swift 3, with no
change to AppKit,
just by making these
changes in Foundation,
this class looks like this.
You see we've got the struct
date type, and we no longer need
to mark this as @NSCopying
because they're value types,
and we handle the
copying for you.
Now there can be a performance
cost for crossing this bridge
and to explain what that is, I'd
like to dive into some details
on how the bridging
actually works.
We have two major strategies for
bridging, one for large types,
which hold a reference, and
a second for small types,
which create a reference.
So, for example, we're
going back to data.
Here I've created data
again, and you see a struct
that wraps a reference type.
Now, if I call some
Objective-C API, what happens is
that we hand the reference
over to the Objective-C side.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
that we hand the reference
over to the Objective-C side.
That's because, of course,
Objective-C doesn't
deal with struct Data.
It only understands NSData.
Now, in this case perhaps
a synchronous method call,
that Objective-C code isn't
going to hold onto that data
for any period of time.
It may access it, and
then forget about it.
So, just holding the reference
for a short period
of time is enough.
On the other hand, you'll see
many APIs that, for example,
take a data for longer period
of time, usually marked
as properties that have
the copying attribute.
In that case, in Objective-C,
this Objective-C code will
call copy on that data,
and that's because it
needs to protect itself
from any potential mutation
that happens to that data
that it just received from
a totally unknown source.
So that means that when crossing
this bridge, a copy can occur.
Let's flip that around
the other way.
Let's say I've got
some Swift code
that is calling an Objective-C
method that returns some data.
Here, the Objective-C
code has, of course,
created the class NSData and
when it's returned to Swift,
we create the struct Data,
which wraps the reference
and it calls copy, for exactly
the same reason as we saw
in the previous slide.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
in the previous slide.
The struct needs to maintain
its control over this copy
so that it can provide the
proper value semantics for you.
Fortunately, almost all data
that you receive this way
from the SDK is immutable,
which means that the copy
is actually just a retain.
However, it is important
to understand
that when crossing this
bridge, a copy may occur.
For small types, like Date, you
can see there is no reference.
We saw earlier the
implementation,
just had a double.
So, in Swift, if we call an
Objective-C function, or method,
which takes a date, then we
have to allocate an NSDate
on the bridging, and
that's again, of course,
because the Objective-C
code only knows how
to deal with references.
Now, we do a lot of tricks in
Objective-C to make allocation
of things like NSDates
really cheap.
However, it is important
to understand
that an allocation can
occur on that bridge.
So, we optimize these
sites for use within Swift.
In your code, you should
avoid crossing back and forth
over that bridge repeatedly.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
over that bridge repeatedly.
This is because we wanted our
code to be safe by default,
but it does mean that there
is a potential copy there.
So, something to be aware
of when you're looking
at adopting these
new value types.
Next, let's talk
about migration.
So, first, some good news.
These new types we're
talking about today exist
for all Swift deployment
targets.
They're part of the
Swift Standard Library,
which means you don't need
to wait for your customers
to upgrade to the newest
versions of our platforms.
As soon as Swift 3 and
S Creator are released,
you can begin using
them immediately.
Now, to help you, we've of
course upgraded the Migrator,
and that means that when you
open your project in Xcode 8,
you'll see a dialog box like
this one, and I recommend
that you click convert.
So, let me show you a few things
that the Migrator
will do for you.
So here we have in
Swift 2.2 some NSDates,
and we're calling a method on
that, dateByAddingtimeInterval.
The Migrator will fix up
the reference type NSDate
into the value type
of struct Date,
and it will change the methods
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and it will change the methods
because they've changed
according
to our new Swift 3
API Design Guidelines,
both for the reference types
and for the value types.
Here's another example.
Here, I'm creating an
NSDateComponents in Swift 2,
and then setting some of its
properties, and I can do this
because NSDateComponents is an
always mutable reference type.
Now, in Swift 3,
we've introduced a
struct DateComponents.
So the Migrator will change
the reference to the struct,
but also it notices that you're
mutating it, and changes the let
to a var for you as well.
Now the Migrator can
do quite a bit for you,
but there are some places
where if you go back and look
at what it's done, you can do
even better by taking advantage
of some additional things
that we've added for you.
In this case, DateComponents
has a new initializer,
and this is something
we can only do in Swift.
The initializer has
arguments for every property
in the DateComponents,
and they're all optional,
and they all have
default values,
which means that you can create
a DataComponents using only the
values you care about, your
month and day in this case.
And you can change
the var back to a let
because now you don't
need to mutate it
after you've initialized it.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
after you've initialized it.
And finally, our
friend data again.
Here in Swift 2, see that I'm
creating an NSMutableData,
the reference type, and
appending some data to it.
In Swift 3, the Migrator
will fix up the method names,
like contentsOf URL,
and appendData,
and it will change NSData
into the struct Data.
However, it's left the
NSMutableData reference
type alone.
In some cases like this, there's
just not enough information
for the Migrator in order
to do what we think is the
best option, so we're going
to leave it as is and
it should still work.
However, if you go back and
do some additional fix ups
on your own, you can
do something cool here.
We can change the
MutableData into a struct Data,
which means that we
change it from let to var.
And we can remove
the options argument
because it has a
default value now.
So, we've talked
about a lot today,
and I'd like to just
briefly recap what we saw.
We believe that these
improvements
to Foundation are going
to benefit the entire SDK
and your whole development
experience in Swift.
X-TIMESTAMP-MAP=MPEGTS:181083,LOCAL:00:00:00.000
and your whole development
experience in Swift.
Partly that was due
to the API renaming,
but we also took the
opportunity to go farther,
and add a brand new
set of value types,
and a lot of new
Swift-specific API.
We see this as the start
of a journey, and we intend
to continue to be this
leverage point in the future.
We're going to make many
improvements over time
to make your Swift apps safer,
faster, and more expressive.
So for more information,
check out this struct URL,
and these related sessions,
including, Going Server-side
with Swift Open Source,
Measurements and Units.
[ Applause ]
Thank you.
[ Applause ]