Access Control

Introduction

Welcome to the first lesson of What’s New in Swift 4. Today, you will learn ways to prevent others from messing around with your code. You will learn the benefits of doing it and even control how much others can mess around with your code. Let’s get started.

Problem

I don’t want you to use my code.

open, public, internal, file-private, private, who are they?

Why is this important?

  • Reduce indexing/compilation time while building an app
  • Apple Engineers do not want developers to touch their code, sometimes
  • No need to overwhelm your teammates with unnecessary methods

5 Levels of Access Control

  1. private (Most Secure)
  2. fileprivate
  3. internal
  4. public
  5. open (Least Secure)

Private

Only available within the scope, {}

Ex 1) Game Application

  1. class Game {
  2. private var number = 0
  3. var score: Int {
  4. return number
  5. }
  6. func increaseNumberByOne() {
  7. number += 1
  8. }
  9. }
  10. Game().number // Error
  11. Game().score // Good

Ex 2) Singleton

In the single pattern, there is a private method for initialization to prevent extra initialization.

  1. class AccountManager {
  2. static let sharedInstance = AccountManager()
  3. var userInfo = (ID: "bobthedev", Password: 01036343984)
  4. private init() {} // Prevent public initialization
  5. }

You are not allowed to initialize the AccountManager class outside the “scope” of AccountManager.

  1. AccountManager() // Error

Swift 4 Private Extension

Before Swift 4, it was not able to use anything that has to do with private even with extension. However, it is possible in Swift 4. For example,

  1. class MyStatus {
  2. private var isHappy = true
  3. }

You have access to isHappy within extension.

  1. extension MyStatus {
  2. func checkStatus() {
  3. print(isHappy)
  4. }
  5. }

Nice and easy

Private Setter

There is a problem with using private because it is good for encasulating, but it is not accessed outside the scope at all. To prevent that from happening, we may use, private(set). It states, you have access to this property/function but it can be only mutated/changed within the scope.

  1. class Human {
  2. private(set) var name: String
  3. init(enterName: String) {
  4. name = enterName
  5. }
  6. }
  7. let bob = Human(enterName: "Bob Lee")
  8. bob.name = "Bobby" // Error

File Private

As the name indicates, it is only accessible within the file. Create two files, NewViewController.swift and ViewController.swift.

  1. // NewViewController.swift
  2. fileprivate class NewViewController: UIViewController {
  3. override func viewDidLoad() {
  4. super.viewDidLoad()
  5. }
  6. }

You’ve declared that NewViewController is fileprivate.Let us attempt to access the class in another file.

  1. // ViewController.swift
  2. class ViewController: UIViewController {
  3. override func viewDidLoad() {
  4. super.viewDidLoad()
  5. // let newViewController = NewViewController() // Error
  6. }
  7. }

Impossible.

Internal

Anything has to with internal is accessed within the same module. intermal is automatically applied if you do not specify one’s access level. For example,

  1. // file.swift
  2. var name = "Bob"
  3. internal var name = "Bob"

They are both identical.

Understanding Module

Simply put, a module is just one Xcode project. To be more specifc, take a look at the definition below.

Definition: 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.

UIKit is also considered as one module. When you import an external library as shown below,

  1. import RandomLibraryFromGithub

RandomLibraryFromGithub is a single module. It is probably one Xcode project.

If RandomLibraryFromGithub contains an internal method as shownb below, you do not have access to the method in your project.

  1. // RandomLibraryFromGithub.swift
  2. funt hello() {
  3. print("From RandomLibraryFromGithub")
  4. }

Let’s attempt to import RandomLibraryFromGithub in your currnet project and execute hello().

  1. // Your Project
  2. import RandomLibraryFromGithub
  3. hello() // Error: not found

Not possible.

Open

They are similar. You have access to anything that is public or open even if it is imported.

  1. class BobbyViewController: UIViewController {
  2. override func viewDidLoad() {
  3. super.viewDidLoad()
  4. print("hello")
  5. }
  6. }

viewDidLoad is a function that is marked with open. You even have the ability to override it.

Public

If it is marked with public, you have access to it but you don’t have the ability to override. For example,

  1. // RandomLibraryFromGithub
  2. public func A() {}
  3. open func B() {}
  1. // In your current project
  2. override func A(){} // error
  3. override func B(){} // success

Summary of Access Control (low to high)

Control Purpose Example
Open Available every where, override possible UICollectionView, UIViewController
Public Available every where, override not possible UICollectionViewDelegate
Internal Only available within the module Everything you define by default
File-Private Only available within the file items in fileOne.swift not available in fileTwo.swift
Private Only available within the scope private initialization in the singleton pattern

Resources

9001_access_control

Conclusion

In this lesson, you’ve learned the 5 basic levels in Access Control in Swift. Again, remember that it provides quicker compilation/indexing time, less overwhelming of your teammates, and mostly you feel nice and safe. Access control is the fundamental way Apple Engineers protect their source code that we, developers, continue to follow their way. Well, you can do the same for your teammates as well. Keep it simple and stupid.