CloseHomeAboutBlogContactCourse
Bob I’m an iOS instructor/blogger from S.Korea.July 14 • 5 min read • Edit

The Complete Understanding of Access Control in Swift

Differentiate Open, Public, Internal, File-private, Private

Anecdote (You may skip)

Swift is my first programming language, and my geek crush. 6 months ago, I got a D on my physics exam. I paid more attention to her than to physical chemistry and thermodynamics as a formal chemical engineering student.

Not to mention, I don’t remember shit. Quitting school was the best thing ever happened in my life. By the way, I got an A- in English. Just letting my readers know, if I wanted, I could write formally. But, I rather make my articles engaging and put smiles on my readers for a second or two.

I also want to disrupt certain stereotypes that software developers/hackers work behind the desk and can’t communicate.

Anyway, 3 months after, I became comfortable with her. One day, I’ve decided to read open source projects on Github to see what’s up. She shocked me. I thought I knew something about her. Little did I know, it was my distorted perception.

Back to Reality

The reason I got so dumbfounded was that I saw these weird keywords: open, public, internal, file-private, private. They were in front of class, struct, func, var, and everywhere.

When you first learned Swift, the whole experience shouldn’t seem too foreign to you. Btw, if you are like, “wtf”, right now, don’t worry. By the time you get to the bottom, everything should be alright, hopefully. ✌️

Let’s Begin

Before we talk about those keywords mentioned above, you have to understand one thing: module. Imagine a module is a bundle of code. Your single Xcode project/framework/bundle is considered as a single module.

Even UIKit is considered as one module. For example, when you try to interact with UIComponents such as UITableView, UIButton, UIViewController, and so on, you have to import the UIKit library/module on the top.

import UIKit
class BobController: UIViewController {}

So, now you are using code written in UIKit. Xcode project natively doesn’t contain all those Swift or Objective-C files, so you must import. I don’t know where UIKit is located in the Xcode folder, but it certainly exists somewhere.

Apple engineers don’t tell iOS developers how UIKit is designed internally along with Xcode. Only Swift is open-sourced.

So, when you want to import someone’s code, for example, a random library from Github, you can drag the library/folder onto the left side of the Xcode panel where all the files are located at, and you import,

import RandomLibraryFromGithub

If you aren’t too clear with what a module is by now, Apple says,

A module is a single unit of code distribution — a framework or application that is built and shipped as a single unit and that can be imported by another module with Swift’s import keyword.

So what? 🤔

Great, you’ve come a long way. However, there are times when you don’t want to mess around with what you’ve just imported. For example, UIKit engineers at Apple don’t want iOS developers to touch or modify some of its classes, methods, variables, and functions. I mean, we could implement own structures with, for example,UICollectionView by overriding or subclassing, but we can’t mess around with how Apple engineers designed it so that they were able to let us use UICollectionView without us coding them manually.

Maybe that was a shitty analogy. Imagine, you are a father and you gave your 5-year-old how to use a computer. But then your daughter/son begins to open up the entire computer and try to “customize” things. Same thing. Apple engineers don’t want us to mess around with their code. So, they’ve created some sort of barrier/entry level to block us from having access to their library/code. That’s why it’s called, Access Control. Too obvious, isn’t it?

There are 5 types in Swift 3. It may sound quite a lot, but I will try not to overwhelm you by giving you concise but clear examples for each. Let’s begin with the least control.

1. Open (Least Control)

Now, Let’s take a look at how UIKit framework engineers have designed their code. For example, we can always subclass UICollectionView to our own.

myCollectionView: UICollectionView { }

Great, but how is this possible that we can subclass? To find the answer, I’ve option + click on the UICollectionView class.

@available(iOS 6.0, *)

open class UICollectionView : UIScrollView { }

open is to indicate that you have access from the defining module which is UIKit. You can even subclass as shown by myCollectionView even though UIKit is a separate module from my own App bundle.

2. Public

Well, public is identical to open except one thing. You have access to another module. For example, from you app bundle/Xcode project, you have access to theUICollectionView class. But, now let’s take a look at UICollectionViewDelegete

public protocol UICollectionViewDelegate : UIScrollViewDelegate {}

Well, don’t worry if you aren’t familiar with protocol or delegate. The point is that we can’t subclass UICollectionViewDelegate in our own.

It can be only overridden by subclasses only within the module where they’re defined. Since UIKit is hidden, and we, developers, have no idea.

3. Internal (Default)

The reason you don’t see often of this is that when you create a function, variable, class, it’s internal by default. Those that are marked with internal can be used only within any source files from their defining module, but not in any source file outside of that module.

Internal functions created by UIKit engineers can not be accessed by iOS developers even if we import UIKit. For example,

// A function Apple UIKit Engineers wrote in UIKit

internal func useMeIfYouCan() {
 print("You can't stop me")
}

Even if we import UIKit, unlike UIViewController and many other public/open functions and classes, there is no way for us to use useMeIfYouCan.

4. File-Private

fileprivate is used when you want functions/class/variables to be used just within one single swift file. For example,

// random.swift

fileprivate func introduce() {
 print("Hello from the other side")
}

There is no way you can use that function/class in a different file even if you are in the same module. For example,

// viewcontroller.swift

override func viewDidLoad() {
 super.viewDidLoad()
 introduce() // error
}

5. Private (Most Control)

Lastly, this is the simplest. There is no way for you to use/access when you “escape” out of classes, functions, or methods. For example,

// human.swift

class Human {
 private var name = "Bob"
}

Human() // Good
Human().name // Error

That’s it.

About Me

iOS Developer from South Korea. Feel free to follow my story on Instagram or get serious on LinkedIn