Swift Programming 101: The Power of Extensions

Extensions are one of Swift's best features. Extensions allow you to add behavior to existing classes, including classes in the Cocoa Touch Framework. Apple can't add every feature you want to their framework classes, but they have provided a tool to allow you to do it yourself! In this article, you will learn practical uses for Swift extensions you can use immediately in your iOS projects.

Master your iPhone in one minute a day:

Sign up to iPhone Life's Tip of the Day Newsletter and we'll send you a tip each day to save time and get the most out of your iPhone or iPad.

Swift Extensions

Swift's extensions allow you to extend classes, structures and enumerations without creating a subclass. It's better to create an extension to add functionality to a Cocoa Touch Framework class than to create a subclass, because it allows you to use the standard Cocoa Touch class throughout your app. For example, if you add an extension to the NSURL class, you can still use NSURL throughout your app. You don't have to remember to use a custom subclass in some places and NSURL in others.

You can add these items to a type using extensions:

  • Instance and type methods
  • Computed instance and computed type properties
  • Initializers
  • Subscripts
  • Conformance to a protocol

Here is the basic syntax for declaring an extension in Swift:

Creating Custom Extensions

To see how Swift extensions work, let's add a new method to Swift's String class.

By default, String has no method that tells you the number of times one string occurs in another string. For example, you may want to know how many commas are in a string. Since String doesn't have this method, you can add it using an extension.

I've already created an extension for you. Download the ExtensionsDemo sample project at this link so you can take a look.

  1. After downloading the ExtensionsDemo project, open it in Xcode.
  1. Select the StringExtensions.swift file in the Project Navigator to see the following extension declaration:

The extension keyword is followed by the name of the class being extended—in this case, String. The extension declares an occurrencesOfString method that accepts a String parameter named aString. This is the string you are searching for. The return value is an Int that contains the number of times aString is found in the string you are testing. Within this method, self refers to the string object you are searching!

  1. Let's see how this extension works at run time. In the Project Navigator, expand the ExtensionsDemoTests.swift file. This file contains the testExtension method:

  1. The StringExtensions.swift class is not included in the unit test project's target. To verify this, type the letters s.o after the constant declaration:

The occurrencesOfString method doesn't appear in Code Completion, because the extension hasn't been included in the unit test target. Let's change that.

  1. Select StringExtensions.swift in the Project Navigator. Go to the File Inspector on the right side of the Xcode window, and under Target Membership, select the ExtensionsDemoTests check box (Figure 1).
Figure 1 - Select the ExtensionDemoTests target.
  1. Select the ExtensionDemoTests.swift file in the Project Navigator. Enter the code s.o and the occurrencesOfString method appears in Code Completion (Figure 2).
The method in Code Completion
Figure 2 - The String extension appears in Code Completion!
  1. Add the following code to the testExtension method:

This code checks the number of times "the" appears in the string. It should appear twice!

  1. Set a breakpoint by clicking in the gutter to the left of the second line of code (Figure 3).
Set a breakpoint
Figure 3 - Set a breakpoint on the second line of code.
  1. To run this method, go to the Test Navigator by clicking the fifth button from the left in the Navigator toolbar. Then click the arrow to the right of the ExtensionDemoTests node (Figure 4).
Run the unit test
Figure 4 - Run the unit test.
  1. When you hit the breakpoint, click the Step over button in the Debug toolbar and the count variable is set to 2 in the Variables View (Figure 5).
Two occurrences have been found
Figure 5 - Two occurrences have been found.
  1. Click the Continue button in the Debug toolbar and Xcode indicates the testExtension method has passed.

Adding Computed Properties

Swift's extensions can add computed instance and type properties, but they can't add stored proeprties or property observers to existing properties.

Let's look at an extension that adds a computed instance property to the UIImage Cocoa Touch class.

  1. In Xcode, select File > Open and navigate to the folder where you downloaded this post's sample code. Drill down into the ExtensionsDemo project, select the Extensions.playground file and click Open.
  1. The playground contains the following extension of the UIImage class:

This extension contains a single property named halfSizeImage. It takes the existing image (if any) and returns a half-size version of it. Let's give it a try.

  1. Add the following code to the bottom of the playground:

This code creates a UIImage object from the Book4iOS8.png file, which I have added to this playground's resources. When you enter this code, the image size is displayed in the playgrounds sidebar (Figure 6).

Figure 6 - The image is 250 x 327
  1. Hover your mouse pointer to the right of the image size and click on the Quick Look icon (the eye) to see the image (Figure 7).
Figure 7 - Hover over the Quick View icon to view the image.
  1. Now add the following code to the storyboard that references the halfSizeImage extension property:

  1. When you enter this new line of code, the sidebar displays the size of the new image returned from the computed property, half the original size (Figure 8).
The half-size image
Figure 8 - The half-size image is 125x164
  1. Hover your mouse pointer to the right of the new line of code and click the Quick View button to see the half-size image (Figure 9).
Quick View shows the half-size image
Figure 9 - Quick View shows the half-size image

The extension's computed property is working!

Adding Subscripts

Extensions.playground contains another extension that demonstrates how to add a subscript to an existing class:

This subscript accepts an integer index value and returns the character at that index.

  1. Add the following code to the bottom of the playground to test this extension:

  1. This code creates a String variable containing 26 characters, then requests the character at position 0. The results sidebar shows the values in Figure 10.
Figure 10 - The subscript extension at work!

This is exactly right. The first character in the string is the letter B.

Try experimenting with other values, including negative numbers and numbers greater than 25. The subscript returns nil in both cases.

Extension Rules

Here are a few more things to note about extensions:

  • You can add more than one member to a class in a single extension.
  • It's a best practice to add related methods to a single extension.
  • There is no limit to the number of extensions you can add to a class.
  • Members added to a class by an extension are inherited by subclasses. 

Conclusion

Hopefully, you can see the power of extensions and how they can be applied in practical ways to make your day-to-day coding easier. Extensions allow you to solve a problem once and reuse the solution many times in multiple iOS projects. Remember, it's a best practice to create extensions rather than subclassing Cocoa Touch Framework classes where possible!

 

Master your iPhone in one minute a day: Sign up here to get our FREE Tip of the Day delivered right to your inbox.
Topics: 

Kevin McNeish is author of the new book “Learn to Code in Swift” as well as the “iOS App Development for Non-Programmers” book series (www.iOSAppsForNonProgrammers.com), winner of the Publishing Innovation Award. Kevin is also an award-winning app developer, software architect, and conference speaker in the U.S. and abroad. He has spent much of his career making difficult concepts easy to understand. Follow Kevin on Twitter: @kjmcneish.