Access Control - ADDITIONAL TOPICS - Understanding Swift Programming: Swift 2 (2015)

Understanding Swift Programming: Swift 2 (2015)

PART 3: ADDITIONAL TOPICS

27. Access Control

Swift includes a capability for controlling access to particular pieces of code and particular types, properties, methods, and the like.

This is most commonly used for frameworks that you create that are used (by importing the framework module) by your apps.

Developing your own framework is a common practice if you have code that you want to use in more than one app. And if it is generally useful you may want to provide it to other developers.

In defining a framework, it is frequently the case that you want users of the framework to be able to access only certain entities (e.g., classes, methods and properties) that you define as the official API for the framework. You typically don't want developers using the framework to be able to access other entities that you want to be able to change without giving notice. This is done by controlling access. Typically, the official API is designated as public while other capabilities are designated as a level less than public.

Access is controlled based on two factors. One factor is where the code you have imported and are attempting to run came from. The other factor is the level of access allowed for a specific type depending upon tagging using three defined tags: public, internal, and private.

Where the Code Came From

When you import code into a program, that code comes from somewhere. It might come from a different module than the module where your program is, it might come from the same module (but a different file), or it might come from the same module and the same file where your program is.

The table below shows what access level is required (as specified in the code for particular entities) to gain access to code, depending upon where the code came from. A checkmark means that access is allowed for that particular access level—public, internal, or private.

There are three situations.

First, if you are running code imported from a different module, the level of the entity you are trying to access in that code must be public. If the level is internal or private, you will not be able to access it. (See below for how this level is determined.)

Second, if you are running code in the same module but a different file as your app, the level of the entity you are trying to access in the code being imported must be either public or internal. If the level is private, you will not be able to access it.

And third, if you are running code in the same file as your app, access is always allowed, regardless of the level of access defined in the code.

How the Code is Tagged

Every entity (meaning type, method, or property) has an level of access control level associated with it. This is determined by what can often be a fairly complex set of rules that can be different for specific types.

However, a few general rules will suffice for most developers in most situations. First, if you are building an app, rather than a framework, you will be writing code that is in one of the files in the module that is the target. If you do nothing in this code, all of the code will be tagged as having an access level of internal (the default), and that code will run regardless of where it is as long as it is in the same module. So you will not have to worry about access levels. In building your app you may use standard frameworks that you import. If they have been properly defined, the classes, methods, and properties that you access will be part of the official defined API for that framework, and those entities should have the access level of public and the code in your app will be able to access them.

If you build a framework, or need to use more restrictive access levels in your app, you may need to understand some of the more detailed rules about access control, and you should consult the Apple documentation.

A general rule about access is that the access level for an entity cannot be less restrictive than the access level of the most restrictive access level of the components for the entity. The previous sentence is pretty hard to parse, so to make it clearer, see the following example.

First, to understand the example, let's say that you've defined a custom class and created an instance of that class and then called a function:

private class Trout {

var species = "rainbow"

}

func printSpecies () {

print("Species is \(aParticularTrout.species)")

}

This is called with:

var aParticularTrout = Trout()

aParticularTrout.printSpecies()

So, we have defined a class with an access level of private, and then a function with an access level of internal (since it is not explicitly specified and the default access level is internal.)

The access level of the function printSpecies might be assumed to be internal (since its type is not specified and internal is the default), but note that it uses an input parameter with a type of Trout. And we have explicity tagged the custom class Trout as having an access level of private. The level public, remember, is the least restrictive (it will always run), while private is the most restrictive. Because the input parameter for printSpecies is very restrictive (private), the access level for printSpecies will not be internal butprivate.

Hands-On Exercises

Go to the following web address with a Macintosh or Windows PC to do the Hands-On Exercises.

For Chapter 27 exercises, go to

understandingswiftprogramming.com/27