Apple’s Swift 2.0: What You Need to Know

Screen Shot 2015-10-06 at 9.53.15 AM

When Apple launched Swift in June 2014, it caught the programming world by surprise; few had expected the company to issue a replacement for Objective-C, the aging programming language used to build apps for iOS and Mac OS X.

Within months, Swift had steadily climbed the rankings of most buzzed-about programming languages. Earlier this year, Apple updated the language with a collection of new features, including a new error-handling model. By the end of 2015, if all goes according to plan, Swift will become open source under an OSI-approved permissive license.

So what’s changed with Swift 2.0? Once you get under the proverbial hood, the answer is: Lots. This is largely due to the fact that Swift was released in an incomplete state, so many of the updates tackle bugs and performance improvements. Here are the biggest changes (all examples are run in the iswift.org playground):

Guard

At first glance, Swift’s Guard statement seems like an alternative to “If,” built to simplify code by only running a portion of it if the tested conditions aren’t met (there’s always an “Else” with Guard).

But under normal circumstances, conditional constructs (“If -> Then -> Else”) require a good deal of code to deal with potential options and unwrapping. Contrast that with Guard, which automatically performs any needed unwrapping for options.

In the example below, “x” is passed as an optional int, so it can have a value or be nil. To access the int value of “x,” I normally have to unwrap it, but the Guard statement can do that for me. (I’ve used var after the Guard, as let would not allow it to be modified.) Change var to let and you’ll see the compiler barf at x = x +4.

[cpp]

func foo(x: Int?) {

guard var x = x where x > 0 else {

print ("Bad Params.")

return

}

// Use x

x = x + 4

print(x)

}

foo(6)

foo(nil)

[/cpp]

When run, this outputs:

[cpp]

10

Bad Params

[/cpp]

Guard logic is kept separate from the function’s logic code. Useful!

If It Looks Like Exceptions…

So-called “errors” in Swift are more akin to the exceptions found in C#, Java, and other programming languages. Swift’s error handling, introduced in Swift 2.0, lets you specify which methods, functions and initializers can throw errors.

Swift uses an elegant method of defining possible errors as enums. Here I’ve defined two InkError enums. The function checkInkError() calls to two ink functions (not shown), and if either fails, then it throws the appropriate exception:

[cpp]

enum InkError: ErrorType {

case OutofInkError

case InkDriedError

}

func checkInkWithError() throws {

if ink.isAvailable() {

if ink.LiquidState() {

// can print – comes back without exception here

} else {

throw InkError.InkDriedError

}

} else {

throw InkError.OutofInkError

}

}

[/cpp]

It’s one thing to throw errors, but another entirely to catch them; any that propagate will kill your iOS app dead. Note how the keywords “do,” “try” and “catch” are used here; if you’re used to “do” loops in C/C++, Swift’s version can prove confusing, but not impossibly so.

Here’s a function code that checks the ink:

[cpp]

func tryToPrint() -> Bool {

do {

try

checkInkWithError()

return true

} catch {

print("Ink needs replacing!")

return false

}

}

if (tryToPrint()) {

print("Can Print")

}

else {

print("Cannot print")

}

[/cpp]

In an interesting twist, you can also turn Swift into Java (!) by having multiple catches (a.k.a., checked exceptions in Java), each specifying one of the enums. Note that you also need an extra catchall, or else the compiler gets upset. As an example, I’ve expanded the tryToPrint():

[cpp]

func tryToPrint() -> Bool {

do {

try

checkInkWithError()

return true

} catch InkError.OutofInkError {

print("More ink could be useful!")

return false

} catch InkError.InkDriedError {

print("Ink dried out – replace cartridge!")

return false

} catch {

print("Unspecified printer ink error")

return false

}

}

[/cpp]

Do What?

If you decide to use “do” in do-while loops, you should alter “do” to repeat; for instance:

[cpp]

var i = 0

repeat {

print(i)

i++

}

while i < 10

[/cpp]

Simple API Availability Detection

While Swift already made it possible for the app to detect the exact version of the underlying operating system, if #available lets you easily specify the platform name and version, whether iOS, OSX, or even watchOS. The following example detects that the system is running iOS 9.x:

[cpp]

func isiOS9() -> Bool {

if #available(iOS 9, *) {

return true

}

else {

return false

}

}

if isiOS9() {

print("Yay- we have iOS nine")

}

else {

print("No- have iOS eight or seven")

}

[/cpp]

There’s also @available, which is an attribute that you use to mark functions and classes as being available to that version. For complex applications that need to run on multiple versions of iOS, this simplifies the task.

[cpp]

@available(iOS 9, *)

func doSomethingiOS9() {

print("iOS 9 stuff")

}

if #available(iOS 9, *) {

doSomethingiOS9()

}

else {

print("Need to upgrade to iOS 9")

}

[/cpp]

Note that you need to check if the function can be called from code, as well. Would it cause an error by calling code that’s not available? (I’m guessing it would.) You can’t use this for function overloading, i.e., you can’t define the same function three times with an @available for three different OS versions.

String Interpolation Now Includes String Literals

String interpolation lets you build a string from a mixture of constants, variables, literals, and expressions by including values inside a string literal. It’s a very handy way for initializing strings:

[cpp]

let astring ="a string literal"

[/cpp]

Originally, string interpolation only worked with variables as a backslash followed by the variable in brackets.

[cpp]

let myName="David Bolton"

print ("My name is \(myName)")

[/cpp]

Run that and it outputs,

My name is David Bolton.

With Swift 2.0, you can put expressions inside the brackets, provided they don’t contain unescaped backslash \ or double quotes ” or line feed\carriage return. The backslash character (as in C, etc.) is what you use to escape characters; in order to print a backslash, double it up:

[cpp]

let backslash="\\"

print ("A backslash is \(backslash)")

[/cpp]

Removing one of the \ from the first line gives an un-terminated string literal error. For simple expressions, use this:

[cpp]

print ("My age is \(50 + 6)")

[/cpp]

Prints:

My age is 56.

Guess the output of this little snippet:

 

[cpp]

let a="1 2 \(1 + 2)"

let b = "\(a)"

print (b)

[/cpp]

The answer: 1 2 3.

Conclusion

Swift continues to improve, and it’s clear that Apple is pushing a lot of resources at it. Once the platform goes open-source, expect community contributions to help refine and expand its capabilities.

Image Credit: Apple

Post a Comment

Your email address will not be published.