Your privacy matters: This site uses cookies to analyze site usage and provide social media features. Learn More.

Thinking in Swift (Part III) – Optionals

January 20, 2015 in Mobile Development Articles

Written by Jason Bell


The one topic that seems to present the most difficulty for developers new to the Swift programming language is the concept of optionals. The basic idea is relatively simple to understand – there has to be a way to allow for a variable to be empty (a state most languages identify as null or nil).

I think the reason most developers have trouble is because of the unique syntax and variety of shortcuts that the language provides. Another issue is that the documentation and many other articles focus almost exclusively on the mechanics and don’t spend enough time on the “why.” So, in this article, I’ll do my best to address both.

Value Types, Reference Types, and the Other Guys

Most modern compiled languages (including Java, C#, and Swift) group data types into two separate categories – value types and reference types. Value types contain their value directly while reference types contain the location to another place in memory where the actual value is stored.

The main reason for this distinction is performance. Reference types are very flexible and necessary to support many features of object-oriented programming. They are used for strings and objects. However, they require more work to deal with at runtime. Therefore, value types are better for simple things like integers and Boolean values.

This all makes sense but introduces a wrinkle – reference types can easily accommodate a variable that doesn’t have a value. The variable is simply set to null (or nil).

    Person *p = nil; // Objective-C
    Person p = null; // Java
    Person p = null; // C#

With a value type, however, you cannot do this. A value type can represent the value zero but cannot accommodate the concept of null.

    int i = nil;  // Invalid Objective-C
    int i = null; // Invalid Java
    int i = null; // Invalid C#

To address this issue, each language includes a way for a value type to be null. For each of these languages, you can accomplish this by wrapping a value type with a reference type. In the case of integers, Objective-C has NSNumber, Java has Integer, and C# has Nullable<int> (also can be written as int?). Along with each of these types, there is way to check if the wrapper has a value and a way to access the wrapped value. When Swift was developed, this issue had to be addressed yet again. So, what did the architects of Swift decide to do? Did they follow the crowd, go a completely different direction, or find some sort of middle ground? Let’s see…

Swift = Value Required

One decision the designers of Swift made was to enforce “value required” for every type of variable (value types and reference types). This is different from the other three languages we have looked at.

    var i:Int = nil    // Invalid Swift
    var p:Person = nil // Invalid Swift
    let p:Person = nil // Invalid Swift

The motivation for this rule is to allow you to write cleaner, more robust code. A very common mistake is to write code that accesses a variable without a value. This type of mistake typically causes the application to crash with a “null reference exception” or similar message. Your job (and the compiler’s job) can be made easier by guaranteeing that every variable will always have a value.

Okay, I buy that argument but I still have cases where I need a variable to represent “no value”. How does Swift provide for that?

Optionals

Swift does have an answer – it’s optionals. Any time you need a variable that can be null (value type or reference type), you can use the “?” operator to identify a variable whose value is optional. Such a variable can be set to nil to represent an absence of value.

    var i: Int? = 2
    i = nil

A variable declared as an optional is a wrapper object for the underlying variable. Therefore, you cannot directly access the wrapped value.

    var i: Int? = 2
    var j = i + 2   // compile-time error

If an optional is not given an initial value, it is automatically set to nil and you can always check for the presence of a value by comparing the optional to nil.

    if (i != nil) {
      // do something with i
    }

Forced Unwrapping

If you know an optional contains a value (maybe because you used an if statement like in the previous section) then you can obtain the value by using the “!” operator. This is known as “forced unwrapping”.

    var j = i! + 2

Note that if you try to unwrap an optional that does not have a value, an exception will be thrown (so, don’t do that).

Not too bad, right? So, to review…

  • Every variable needs to have a value.
  • If you want a variable that doesn’t need a value, use “?” to make it an optional.
  • To get the value of an optional, use “!” to unwrap it. Of course, make sure to check that it has a value before you do that.

There is, however, quite a bit more to the story and this is the point where people start to get confused. So, I’ll do my best to make sure that doesn’t happen.

Optional Binding

From the previous two sections, you may be thinking, “Wow, this seems really painful. If I want to get the value of an optional, I always have to check its value with an if statement and then unwrap it?” Fortunately, Swift provides a few features that help to ease the pain – the first is “optional binding”.

With optional binding, you can conditionally assign the unwrapped value to a temporary variable:

    if let v = i {
      // do something with v
    }

In the code above, there are two possibilities – the optional variable i either has a value or it doesn’t. If it does, then v gets set to that value and the code block executes. If i doesn’t have a value then nothing happens (unless you add an else block). Optional binding can be especially useful when calling a function that returns an optional. In that case, you probably only want to do something if a value comes back.

Optional Chaining

For this next feature, let’s setup an example. Let’s say we have an object of type Customer. A customer may or may not have a sales representative assigned. So, we define the salesRep property of Customer to be an optional.

    class Customer {
      var salesRep: Person?
    }

At some point during the run of our application, we need to display the name of a customer’s sales representative. How can we do this? First of all, the following code will not compile:

    let name = cust.salesRep.name // compile error

Because salesRep is an optional, it must be unwrapped in order to retrieve the value. So, one option that may work is to use forced unwrapping:

    let name = cust.salesRep!.name
    println("Sales rep is: \(name)")

The problem here is that a runtime error will occur if salesRep is nil. So, another option would be to check the value first or use the feature we just learned about – optional binding:

    if let rep = cust.salesRep {
      println("Sales rep is: \(rep.name)")
    }

Optional chaining allows us to write this a little differently:

    if let name = cust.salesRep?.name {
      println("Sales rep is: \(name)")
    }

Notice the use of the question mark to perform the unwrapping. In this case, you are basically telling Swift “Unwrap this variable unless it’s nil. If it’s nil then just stop and forget about the rest.” That way, you can chain multiple optionals together:

    if let zipCode = cust.salesRep?.address?.zipCode {
      // only executes if customer has a sales rep
      // and that salesRep has an address
    }

Implicitly Unwrapped Optionals

We have arrived at the final Swift feature we are going to talk about in this article – implicitly unwrapped optionals. Sounds impressive, doesn’t it? For this one, let’s setup another example scenario.

Imagine you have a controller object that has variables that point to user interface elements (e.g. a button or a text field). These variables have to be declared as optionals because the elements aren’t there yet when the controller is first created.

    class MyController {
      var myButton: Button?
      var myTextField: TextField?
    }

However, a short time after the controller is created, those elements get set by something else. Then, once they’re set, they will always have a value (guaranteed). So, in other words, it is clear from the way the application is structured that every time you attempt to access these variables, they will always have a value. Unfortunately, you will still have to use an exclamation mark to perform forced unwrapping every time you access one of these variables.

     myButton!.text = "Hello"

Xcode will complain every time you forget to put that exclamation mark there and you will say “But I know the value is there! What a pain! And it looks ugly!” My guess is that a developer on the Swift team had the same experience and so they added the ability to make this situation less painful. You can declare the instance variables as implicitly unwrapped optionals like so:

    class MyController {
      var myButton: Button!
      var myTextField: TextField!
    }

By doing this, you are effectively telling Swift to automatically unwrap the variable whenever you attempt to use it.

    myButton.text = "Goodbye"

Much better. Just remember that you have to be absolutely sure that the variable will never be nil. This is true for controllers and views but may not be in other situations.

Conclusion

As you have seen, the Swift designers sure did get a lot of mileage out of “?” and “!”. If you are new to Swift, you most likely will have many moments of frustration until you get comfortable with optionals. During that process, try to remember these tips:

  • When you need a variable, make it a constant.
  • If it can’t be a constant, make it require a value (the default).
  • If it needs to possibly be nil, make it an optional.
  • When using an optional, program defensively – what if it’s nil?
  • If you know if will never be nil when you’re using it, maybe it should be an implicitly unwrapped optional (or maybe it shouldn’t be an optional at all).

Author: Jason Bell, Accelebrate’s Director of Technology and senior instructor.

Accelebrate offers private Swift training and iOS training and for groups and instructor-led online Swift classes for individuals.


Written by Jason Bell

Jason Bell
Jason is Accelebrate's Director of Technology where he ensures the smooth and effective running of Accelebrate's IT infrastructure to support the organization's continued growth. Jason also is a trainer specializing in Computer software design and development, C/C++, Microsoft .NET, Apple OS X, iOS (Objective-C and Swift), IIS, and more.


Contact Us:

Accelebrate’s training classes are available for private groups of 3 or more people at your site or online anywhere worldwide.

Don't settle for a "one size fits all" public class! Have Accelebrate deliver exactly the training you want, privately at your site or online, for less than the cost of a public class.

For pricing and to learn more, please contact us.

Contact Us

Toll-free in US/Canada:
877 849 1850
International:
+1 678 648 3113

Toll-free in US/Canada:
866 566 1228
International:
+1 404 420 2491

925B Peachtree Street, NE
PMB 378
Atlanta, GA 30309-3918
USA

Subscribe to our Newsletter:

Never miss the latest news and information from Accelebrate:

Microsoft Partner

Please see our complete list of
Microsoft Official Courses

Recent Training Locations

Alabama

Huntsville

Montgomery

Birmingham

Alaska

Anchorage

Arizona

Phoenix

Tucson

Arkansas

Fayetteville

Little Rock

California

San Francisco

Oakland

San Jose

Orange County

Los Angeles

Sacramento

San Diego

Colorado

Denver

Boulder

Colorado Springs

Connecticut

Hartford

DC

Washington

Florida

Fort Lauderdale

Miami

Jacksonville

Orlando

Saint Petersburg

Tampa

Georgia

Atlanta

Augusta

Savannah

Idaho

Boise

Illinois

Chicago

Indiana

Indianapolis

Iowa

Ceder Rapids

Des Moines

Kansas

Wichita

Kentucky

Lexington

Louisville

Louisiana

Banton Rouge

New Orleans

Maine

Portland

Maryland

Annapolis

Baltimore

Hagerstown

Frederick

Massachusetts

Springfield

Boston

Cambridge

Michigan

Ann Arbor

Detroit

Grand Rapids

Minnesota

Saint Paul

Minneapolis

Mississippi

Jackson

Missouri

Kansas City

St. Louis

Nebraska

Lincoln

Omaha

Nevada

Reno

Las Vegas

New Jersey

Princeton

New Mexico

Albuquerque

New York

Buffalo

Albany

White Plains

New York City

North Carolina

Charlotte

Durham

Raleigh

Ohio

Canton

Akron

Cincinnati

Cleveland

Columbus

Dayton

Oklahoma

Tulsa

Oklahoma City

Oregon

Portland

Pennsylvania

Pittsburgh

Philadelphia

Rhode Island

Providence

South Carolina

Columbia

Charleston

Spartanburg

Greenville

Tennessee

Memphis

Nashville

Knoxville

Texas

Dallas

El Paso

Houston

San Antonio

Austin

Utah

Salt Lake City

Virginia

Richmond

Alexandria

Arlington

Washington

Tacoma

Seattle

West Virginia

Charleston

Wisconsin

Madison

Milwaukee

Alberta

Edmonton

Calgary

British Columbia

Vancouver

Nova Scotia

Halifax

Ontario

Ottawa

Toronto

Quebec

Montreal

Puerto Rico

San Juan

© 2013-2019 Accelebrate, Inc. All Rights Reserved. All trademarks are owned by their respective owners.