Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all articles
Browse latest Browse all 4400

What’s New in Swift 3?

$
0
0

WhatsNewSwift3-feature

Swift 3 is coming later this year, and it brings major code changes to all Swift developers.

If you haven’t been following the Swift Evolution project closely, you may wonder what changes are in store, how it will affect your code, and when you should start porting your code to Swift 3. This article is for you! :]

In this article, I’ll highlight the most significant changes in Swift 3 that will impact your code. Let’s dive in!

Getting Started

Swift 3 preview is available in Xcode 8 beta which is out today. While the evolution of Swift 3 is winding down, there still may be a few accepted changes in the next few months. Feature freeze will occur when Xcode achieves GM in late 2016, so you’ll have to hold off until then before you release Swift 3 apps to the App Store.

To allow developers to make the migration to Swift 3 on their own terms, Apple has included Swift 2.3 as a minor update bundled with Xcode 8. To you as a developer, Swift 2.3 is the same as Swift 2.2 but with support for many of the new SDKs and Xcode features announced at WWDC. Once Xcode 8 comes out of beta, you will be able to submit apps using Swift 2.3 if you have not yet migrated your code to Swift 3.

I recommend trying out the features we discuss in a playground and maybe even running the Migration Assistant on one of your projects so you can get a feel for everything that is changing. But since you can’t release an app to the App Store until Xcode 8 is out of beta and Swift 3 is final, you may want to consider waiting to port your code to Swift 3 until things settle down.

Migrating to Swift 3

When converting to Swift 3, you’ll notice that practically every file needs changes! That’s largely because, all the Cocoa API names have changed. Or to be more precise, the API is the same, but there’s one name appropriate for Objective-C and one name appropriate for Swift. Swift 3 is going to make Swift much more natural to write in the years ahead.

Apple has included a Migration Assistant with Xcode 8 that can brilliantly make most of these changes in one fell swoop. Don’t be surprised though if you need to touch up a few areas yourself that the migrator doesn’t handle automatically.

You can convert to either Swift 2.3 or Swift 3 immediately. If you ever need to bring it back up, you can always navigate in Xcode to Edit > Convert > To Current Swift Syntax…. The compiler fortunately shares the same smarts as the Migration Assistant as well. If you accidentally use the old API on a method call, the compiler will offer a Fix-It option that will help you use the correct modern API.

The best news of all is that Swift 3 aims to be the last release with breaking source changes. So looking forward, you should be able to keep your Swift code from version to version. While the Swift core team can’t predict the future, they have promised that if they do need to break source compatibility, they will offer long deprecation cycles. That means the language has achieved source stability that will encourage more conservative companies to adopt it.

That said, the goal to achieve binary stability was not reached. You’ll find more on the impact of this at the end of this article.

Implemented Swift Evolution Proposals

Community members submitted over 100 proposals for changes to Swift since it went open source. A large number of them (70 so far) have been accepted after discussion and modification. Those that have been rejected have sparked some intense discussion as well. In the end however, the core team makes the final decision on all proposals.

The collaboration between the core team and the wider community has been impressive. In fact, Swift has garnered 30 thousand stars on Github. Several new proposals are submitted every week, week-after-week. Even Apple engineers pen proposals on open Github repository when they want to make changes.

In the sections below, you’ll see linked tags such as [SE-0001]. These are Swift Evolution proposal numbers. The proposal numbers included here have been accepted and will be implemented in time for the final Swift 3.0. The links to each proposal have been included so you can discover the full details of each particular change.

API Changes

The biggest update in Swift 3 involves the standard library adopting consistent naming conventions across libraries. The API Design Guidleines contain the rules that the team settled on as they were building Swift 3, which place a high value on readability and accessibility to new programmers. The core team operated on the principal that “Good API design always considers the call site”. They strove to bring clarity to the point of use. Without further ado, here are the changes most likely to impact you.

First Parameter Label

Let’s start off strong with a direct reversal of a practice you use every day in Swift.

run_backwards_square

The first parameter in functions and methods now always has a label unless you request otherwise. Previously when you called a function or method you omitted the first parameter label [SE-0046]:

// old way, Swift 2, followed by new way, Swift 3
 
"RW".writeToFile("filename", atomically: true, encoding: NSUTF8StringEncoding)
"RW".write(toFile: "filename", atomically: true, encoding: NSUTF8StringEncoding)
 
SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 10)
SKAction.rotate(byAngle: CGFloat(M_PI_2), duration: 10)
 
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline)
 
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
override func numberOfSections(in tableView: UITableView) -> Int
 
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
func viewForZooming(in scrollView: UIScrollView) -> UIView?
 
NSTimer.scheduledTimerWithTimeInterval(0.35, target: self, selector: #selector(reset), userInfo: nil, repeats: true)
NSTimer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(reset), userInfo: nil, repeats: true)

Take note of how the method definitions use prepositions like “of”, “to”, “with”, and ” in” for the external name. These are part of an effort to optimize readability.

If the method call reads well without a preposition and doesn’t need a label, you should explicitly exclude the first parameter name with an underscore:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... }
override func didMoveToView(_ view: SKView) { ... }

In many programming languages, methods may share a base name and offer different parameter names. Swift is no exeption, and now you’ll come across overloaded method names much more since the APIs have been translated to be more direct. Here’s an example with two forms of index():

let names = ["Anna", "Barbara"]
if let annaIndex = names.index(of: "Anna") {
  print("Barbara's position: \(names.index(after: annaIndex))")
}

Altogether, the parameter name changes make method naming more consistent and easier to learn.

Omit Needless Words

In previous iterations of Apple libraries, methods included a name that indicated their return value. Because of the Swift compiler’s type checking, this is much less necessary. The team took a hard look at how to filter out all the noise so that only the signal remains and thus a lot of word repetition has been removed.

chatterbox

The API has gotten smarter about how Objective-C libraries are transformed into native Swift [SE-0005]:

// old way, Swift 2, followed by new way, Swift 3
let blue = UIColor.blueColor()
let blue = UIColor.blue()
 
let min = numbers.minElement()
let min = numbers.min()
 
attributedString.appendAttributedString(anotherString)
attributedString.append(anotherString)
 
names.insert("Jane", atIndex: 0)
names.insert("Jane", at: 0)
 
UIDevice.currentDevice()
UIDevice.current()

Modernized GCD and Core Graphics

Speaking of old API holdouts, GCD and Core Graphics have both received a much-needed makeover.

swift-trimming-shears-square

Grand Central Dispatch is used for many threading tasks such as long calculations or to communicate with a server. By moving activity to a different thread, you prevent locking up the user interface. The libdispatch library was written in the C programming language and has always used a C style API. The API has now been reimagined in native Swift [SE-0088]:

// old way, Swift 2
let queue = dispatch_queue_create("com.test.myqueue", nil)
dispatch_async(queue) {
    print("Hello World")
}
 
// new way, Swift 3
let queue = DispatchQueue(label: "com.test.myqueue")
queue.asynchronously {
  print("Hello World")
}

Similarly, Core Graphics was written in C and in the past used awkward function calls. Here’s how the new way looks [SE-0044]:

// old way, Swift 2
let ctx = UIGraphicsGetCurrentContext()
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
CGContextSetFillColorWithColor(ctx, UIColor.blueColor().CGColor)
CGContextSetStrokeColorWithColor(ctx, UIColor.whiteColor().CGColor)
CGContextSetLineWidth(ctx, 10)
CGContextAddRect(ctx, rectangle)
CGContextDrawPath(ctx, .FillStroke)
UIGraphicsEndImageContext()
 
// new way, Swift 3
if let ctx = UIGraphicsGetCurrentContext() {
    let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
    ctx.setFillColor(UIColor.blue().cgColor)
    ctx.setStrokeColor(UIColor.white().cgColor)
    ctx.setLineWidth(10)
    ctx.addRect(rectangle)
    ctx.drawPath(using: .fillStroke)
 
    UIGraphicsEndImageContext()
}

Capitalization on Enumeration Cases

In another reversal from the way you’ve been used to coding Swift, lowerCamelCase now replaces for enumeration cases. This makes them more consistent with other properties – or values [SE-0006]:

// old way, Swift 2, followed by new way, Swift 3
UIInterfaceOrientationMask.Landscape
UIInterfaceOrientationMask.landscape
 
NSTextAlignment.Right
NSTextAlignment.right
 
SKBlendMode.Multiply
SKBlendMode.multiply

UpperCamelCase is now reserved solely for names of types and protocols. While this may take some getting used to, the Swift team had really good reasoning in their strive for consistency.

Methods that Return or Modify

The standard library is also getting more consistent in method naming with verbs and nouns. You choose a name based on the side effects or the actions taken. The rule of thumb is that if it includes a suffix like “-ed” or “-ing” then think of the method as a noun. A noun method returns a value. If it doesn’t have the suffix, then it is most likely an imperative verb. These “verb” methods perform the action on referenced memory. This is also known as modifying in place. There are several pairs of methods that follow this noun/verb convention. Here are a few of them [SE-0006]:

customArray.enumerate()
customArray.enumerated()
 
customArray.reverse()
customArray.reversed()
 
customArray.sort() // changed from .sortInPlace()
customArray.sorted()

Here’s a snippet of them in action:

var ages = [21, 10, 2] // variable, not constant, so you can modify it
ages.sort() // modified in place, value now [2, 10, 21]
 
for (index, age) in ages.enumerated() { // "-ed" noun returns a copy
  print("\(index). \(age)") // 1. 2 \n 2. 10 \n 3. 21
}

Function Types

Function declarations and function calls have always required parentheses around their parameters:

func f(a: Int) { ... }
 
f(5)

However, when you use a function type as a parameter itself, you might write something like this:

func g(a: Int -> Int) -> Int -> Int  { ... } // old way, Swift 2

You probably notice that it’s fairly difficult to read. Where do the parameters end and the return types begin? With Swift 3 the correct way to define this function is [SE-0066]:

func g(a: (Int) -> Int) -> (Int) -> Int  { ... } // new way, Swift 3

Now the parameter lists are surrounded by parentheses and followed by the return type. Things are clearer, and consequently, the function type is easier to recognize. Here’s a more robust comparison:

// old way, Swift 2
Int -> Float
String -> Int
T -> U
Int -> Float -> String
 
// new way, Swift 3
(Int) -> Float
(String) -> Int
(T) -> U
(Int) -> (Float) -> String

API Additions

While the biggest update to Swift 3 has been the modernization of the existing APIs, there is much more the Swift community has been hard at work at – including several useful additions to the Swift API as well.

Accessing the Containing Type

When you define a static property or method, you have always called them on the type directly:

CustomStruct.staticMethod()

If you are writing code in the context of a type, you still need to include the name of the type to call a static method on the type. To make this a bit cleaner, you can now call Self to get the containing type. The capital ‘S’ refers to the type of self, whereas the lowercase ‘s’ refers to the instance of self.

me-gustaman

Here’s how it works in action [SE-0068]:

struct CustomStruct {
  static func staticMethod() { ... }
 
  func instanceMethod()
    Self.staticMethod() // in the body of the type
  }
}
 
let customStruct = CustomStruct()
customStruct.Self.staticMethod() // on an instance of the type

Inline Sequences

sequence(first:next:) and sequence(state:next:) are global functions that return infinite sequences. You give them an initial value or a mutable state and they will lazily apply a closure [SE-0094]:

for view in sequence(first: someView, next: { $0.superview }) {
    // someView, someView.superview, someView.superview.superview, ...
}

You can constrain the sequence by using the prefix manipulator [SE-0045]:

for x in sequence(first: 0.1, next: { $0 * 2 }).prefix(while: { $0 < 4 }) {
  // 0.1, 0.2, 0.4, 0.8, 1.6, 3.2
}

Miscellaneous Odds and Ends

  • #keyPath() works like #selector() and helps you vanquish typos in stringly typed APIs
  • You now call pi on the type you intend to use it as: Float.pi, CGFloat.pi. And most of the time the compiler can infer the type: let circumference = 2 * .pi * radius [SE-0067]
  • The NS prefix has been removed on old foundation types, you can now use Calendar, Date instead of NSCalendar and NSDate.

Improvements to Tooling

Swift is a language, and a large part of writing it involves using a development environment – which for Apple developers is likely Xcode! The changes going on with the tooling will impact how you write Swift every day.

Swift 3 fixes bugs in the compiler and IDE features. It also improves the precision of error and warning messages. And as you might expect, with each release, Swift is getting faster in how it runs and compiles:

  • By improving string hashing there was a 3x speedup in dictionaries of strings
  • By moving objects from the heap to the stack there was a 24x speedup (in some cases)
  • The compiler now caches multiple files at once (when doing whole module optimization)
  • Code size optimization has reduced the compiled size of Swift code. Apple’s demo Demobots reduced the compiled size to 77% of the original

Xcode is also learning how to think in native Swift:

  • When you right-click on an API method like sort() and jump to its definition, you used to be taken to a cryptic header file. Now, in Xcode 8, you see that sort() is an extension to Array like you would expect.
  • Swift Snapshots are like the nightly releases of Swift Evolution. They offer a chance to work with the new syntax before its fully baked into Xcode. Xcode 8 can load and run Swift Snapshots in playgrounds.

The Swift Package Manager

Open source Swift is actually a family of repositories including the language, the core libraries, and the package manager. Together, this suite makes up what we think of as Swift. The Swift Package Manager defines a simple directory structure for any Swift code that you share and import into projects.

Similar to package managers you may be used to such as Cocoapods or Carthage, Swift’s package manager will download dependencies, compile them, and link them together to create libraries and executables. Swift 3 is the first release to include the Swift Package Manager. There are 1,000 libraries that already support it and in the coming months, you’ll start to see more formatted for it.

Planned Future Features

It was previously mentioned that Swift 3 aims to let you keep your code from version to version in the future by striving to avoid breaking changes. While that is true, there were some loftier, related goals that weren’t reached for this release, namely generics additions and Application Binary Interface (ABI) stability.

The generics additions will include recursive protocol constraints and the ability to make a constrained extension conform to a new protocol (i.e., an array of Equatable elements is Equatable). Before these features are complete, Swift is unable to declare ABI stability.

ABI stabilization will allow applications and libraries compiled with different versions of Swift to be able to be linked and interact with each other. This is a vital step for third party libraries to ship frameworks without providing the source code since new versions of Swift not only require them to update their code, but to rebuild their frameworks as well.

Additionally, ABI stability would remove the need to ship the Swift standard library along with binaries, as is currently the case with iOS and macOS apps created with Xcode. Right now binaries are bundled with 2 MB extra filesize that ensures that they will run on future operating systems.

So to summarize, you can now keep your source code version to version, but the compiled binary compatibility from version to version is not yet here.

Where to Go From Here?

Swift continues to evolve as the community converges on best practices. While still in its infancy, the language has a lot of momentum and a big future. Swift already runs on Linux, and you will likely see it running on servers in addition to devices in the coming years. Designing a language from scratch certainly has its advantages as opportunities to break ABI stability once its locked down will be rare. This is a unique chance to get the language correct without regrets.

Swift is also expanding its reach. Apple is eating their own dogfood. Teams at Apple use Swift on the Music app, Console, picture-in-picture in Sierra, the Xcode Documentation viewer, and the new Swift Playgrounds app for iPad.

Speaking of which, there’s a big push to get non-programmers learning Swift on the iPad and education initiatives!

The takeaway here is that Swift continues its ascent: the names are better, the code reads clearer, and you have the tools to migrate. If you’re inspired to dig deeper, you can watch the WWDC session videos.

There will surely be more to come by the time Swift 3 is finalized in late 2016. We’ll be staying on top of all the updates here, so keep an eye out for tutorials, book announcements, and videos as we start using the exciting changes.

What parts of Swift 3 are you most excited about? What would you like us to cover first? Let us know in the comments below!

The post What’s New in Swift 3? appeared first on Ray Wenderlich.


Viewing all articles
Browse latest Browse all 4400

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>