Access Control Basics in iOS Swift — Part 1

A quick demo of lower levels of access control in Swift

Richard Lu
4 min readSep 10, 2019
Great illustration by undraw.co

In Apple's “The Swift Programming Language (Swift 5.0)," Access Control chapter starts with:

“Access control restricts access to parts of your code from code in other source files and modules.”

Before we can get a better understanding of access control, we have to know what are “modules" and “source files” first.

A module can be imported within other modules as a single unit, which can be a framework or application. For example, when we write import UIKit, UIKit here is imported as a module. The target in our project we are working on is also a module so we can import other modules into it.

A source file is as its name implies, it's simply a .swift file in a module.

Last but not least, when you read the word “entities” in Swift book or below, it refers to “parts of your code” in the quote above.

Levels of Access Control

There are five levels of access control, from highest(least restrictive) to lowest(most restrictive) are open, public, internal, file-private, private.

I will try to use some simple example codes to demonstrate these access levels, and I would like to start from lowest to highest. In this part, I will cover the first 3 lower levels: private, fileprivate and internal.

Private Access

Let’s start with declaring a class named Somebody.

class Somebody {
private var salary: Int = 100000
func gotPromotion(of raise: Int) {
salary += raise
}
}

People usually regard their salary as top secrets to others, so we wrote private var salary, this means it can only be used within this Somebody class (enclosing declaration). We also have func gotPromotion(of raise: Int) for promotion and it will increase the salary with raise amount. We can access the salary variable in that function without runtime error because the function is defined in the enclosing declaration same as salary variable.

let zoe = Somebody()        // salary is 100000
zoe.gotPromotion(of: 3000) // salary is 103000
print(zoe.salary) // runtime error ❌❌❌

Above we created a constant instance of Somebody class named zoe and she got promoted with a raise of 3000(🤑) right away. However, when we try to get her salary value, there will be a runtime error shows. ’salary’ is inaccessible due to ‘private’ protection level . This is because where we declared zoe is not within the same enclosing declaration with private var salary, that is not allowed under private access protection.

From Swift 4.0, if an extension is in the same source file of a declaration, private values can also be accessed within that extension. Let’s try to add an extension to Somebody class in the same file.

extension Somebody {
func gotBonus(of bonus:Int){
salary += bonus
}
}

Now combine everything and give zoe a surprising bonus.

class Somebody {
private var salary: Int = 100000
func gotPromotion(of raise: Int) {
salary += raise
}
}
extension Somebody {
func gotBonus(of bonus:Int){
salary += bonus
}
}
let zoe = Somebody() // salary is 100000
zoe.gotPromotion(of: 3000) // salary is 103000
zoe.gotBonus(of: 2000) // salary is 105000

It works like a charm 🎉🎉🎉

File-private Access

As the name implies, file-private means it can only be accessed within its own defining source file. We can now go-ahead to add a new variable and function in Somebody class to try this out.

Compare to salary, people may be less sensitive about what’s their title at work. We add fileprivate var jobTitle and another func changeJobTitle(to: String) for changing job title value.

class Somebody {
private var salary: Int = 100000

fileprivate var jobTitle:String
= "iOS Developer"


func gotPromotion(of raise: Int) {
salary += raise
}

func changeJobTitle(to newJobTitle:String) {
jobTitle = newJobTitle
}
}
let zoe= Somebody()
// jobTitle is iOS Developer
zoe.changeJobTitle(to:"Senior iOS Developer")
// jobTitle is Senior iOS Developer
zoe.gotPromotion(of:100000)
// salary is 200000
print(zoe.jobTitle)
//
Prints "Senior iOS Developer"

Different to private salary value, when we try to print out zoe’s jobTitle value after changing it to “Senior iOS Developer”, there won’t be any runtime error. However, if we declare another instance of Somebody class in other source files and try to access jobTitle, Xcode will show up a runtime error saying ‘jobTitle’ is inaccessible due to ‘fileprivate’ protection level.

Internal Access

The default access level is internal access. Without specifying an explicit access level when defined, entities will have access level of internal by default, which makes them being usable within all the source files from their defining module.

Compare to the previous two access levels, private and fileprivate, which are both source-file-wise, internal level is module-wise.

In fact, we already used the internal access level in previous Somebody example. class Somebody doesn’t have explicit access level been defined so it automatically has internal access. Let’s say Somebody class is defined in the file Somebody.swift, if now we add a new file called TeamMembers.swift in the same project(module), we won’t have any problem to create instances of Somebody class in this source file.

// TeamMembers.swiftclass TeamMembers {
let a = Somebody()
let b = Somebody()
let c = Somebody()

func promote(_ member: Somebody, to jobTitle: String, with raise:Int) {
member.changeJobTitle(to: jobTitle)
member.gotPromotion(of: raise)
}
}
let members = TeamMembers()
members.promote(members.a, to: "iOS Lead", with: 1000)
print(members.a.jobTitle)
//prints "iOS Lead"

In TeamMembers class, we have func promote(_ member: Somebody, to jobTitle: String, with raise:Int) which calls Somebody class functions changeJobTitle(to:) and gotPromotion(of:), because we didn’t give these functions specific access level in declaration, they also have internal access by default, thus TeamMembers class can call them without restriction.

Hope someone finds this easy to read and helpful to learn about access control. Please write a response if you have any question or advice. In next part we will focus on the last 2 highest access level, open and public. Happy learning~

--

--

Richard Lu

🌞iOS Developer | 🌛2 kids' Daddy | Striving for being awesome day and night