Underlying nearly every iOS, macOS, watchOS, and tvOS application sits the Foundation framework. See how improvements to the fundamental set of API in Foundation will improve the experience of using Swift for the entire Cocoa and Cocoa Touch SDK. Learn how Foundation framework's new value types, adoption of standard library protocols, additional type safety, better generics, and custom operators will also make your own Swift code safer, faster, and more expressive.
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,
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.
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
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.
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.
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.
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,
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,
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
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.
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,
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,
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.
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,
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.
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.
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
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
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
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.
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
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.
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
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
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,
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.
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.
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.
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,
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.
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.
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.
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
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
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
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,
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.
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,
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.
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.
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.
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
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.
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
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.
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.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.