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.
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 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.
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, 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 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 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 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.
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 . 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. 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, 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 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 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 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.
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 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.
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.