Adam Rush

@Adam9Rush

18 December, 2021

Access Control is an essential subject in Software Engineering overall, and it’s super important to consider this when building your application. In addition, access control is a standard subject across all programming languages, and in this article, we’re going to be covering access control in Swift.

Access Control uses keywords across properties, classes, structs, methods, enums and functions. It’s a way to tell the callee what access you have available. It’s best practice to consider this during your build because it means the application’s interface is clear and well understood.

It also allows you to restrict certain parts of your implementation and restrict access to the integration.

Access Control is like deciding what levels of security to have on your house; declaring your door as open will mean leaving your door unlocked and anyone can walk in, whereas declaring your door as private would imply that people can only gain access with a key. This key is only distributed to members of your family.

Swift Keywords

Most languages will define the access control with many keywords, which is no different in Swift. In Swift, we have five levels of access control:

  • open and public
  • internal
  • file-private
  • private

Open & Public Access

This allows any of the enclosing modules to have access to this and any integrator that imports this module. You will typically use this when building a framework or module to define the interface. Open is the least restrictive access control, and it’s worth noting that declaring something open will mean it’s available to your integrators to subclass and effectively override the implementation.

open class SwiftlyBank {}

Internal Access

This is the default access level if nothing is defined, for example:

class SwiftlyBank {}

This class would be described as internal, but for brevity, you can always use the keyword internal, which is always best practice, especially if you’re building a module that will be used outside your application.

The primary role of internal is that it can be accessed throughout the module it’s defined in and not outside.

Also, a public variable can’t have an internal access level because you can’t be sure where this public variable will be used.

File Private Access

The file-private access level is used to make an entire file private, thus allowing you to hide the implementation details of a specific file.

fileprivate class SwiftlyBank {}

This entire file SwiftlyBank is made file-private, meaning everything inside is private throughout your module.

It’s worth noting that fileprivate only this file’s properties can define this class type when you make this class.

Private Access

The use of private is probably going to be the access level you will use the most. Its purpose is to create a specific piece of functionality private to its entity. It means that you can use this private implementation within the declared type.

Let’s take a look at this example:

public class SwiftlyBank {
    private func calculateDepositAmount(with amount: Float) -> Float {
        // Calculation of deposit amount logic
    }
    
    public func makeDeposit(with amount: Float) {
        let depositAmount = calculateDepositAmount(with: amount)
        print(depositAmount)
    }
}

public var bankManager = SwiftlyBank()

// Calculate Deposit Amount isn't accessible here and is private functionality
bankManager.calculateDepositAmount()

// Access the public function
bankManager.makeDeposit(with: 2.00)

The use of private here is great because you’re likely you don’t want to expose the calculation logic to the outside world of your application.

If you’re building a single application, then you’re likely to leave the default access level internal however, within this single application, you might want to take advantage of fileprivate and private to hide these implementation details accordingly.

Enum Types

When creating an enumeration type, all the individual cases will be given the same access level as the defining enum type.

private enum PaymentMethods {
    case visa, mastercard, amex
}

In this example, all the cases will be private because you have defined the PaymentMethods enum as private.

Sponsor

Subscribe for curated Swift content for free

- weekly delivered.