- Published on
Basics of Swift Access Control
- Authors
- Name
- Wayne Dahlberg
- @waynedahlberg
When writing stuctures, class and functions you need to let other code or even other developers know what is available and what is not. This is done by access control prefixing with public
, open
, internal
, private
, and fileprivate
. Access control is another foundational concept that eluded me for years while learning the Swift language.
This is a another post in a series intended as a personal growth exercise. As I learn and digest new things, I want to write about them to solidify my understanding.
These features can restrict team members from accessing, extending or overriding the original implementation of some code. It's very useful when creating a framework or library that is intended to be shared openly among a developer community.
Let's look at module
; an individual unit of code distribution, e.g. your app.
open
and public
are used to declare code accessibility across different modules.
internal
, fileprivate
and private
are used at the Swift file level.
private
// Foo.swift
struct FooStruct {
private let privateStr = "privateStr"
func fooPrintFunc() {
print("\(privateStr)")
}
}
struct FooStructOne {
var fooStruct = FooStruct() {
didSet {
fooStruct.privateStr
}
}
}
// Bar.swift
extension FooStruct {
func fooFunc() {
print("\(privateStr)")
}
}
Given the example above, FooStructOne
tries to access the setter of FooStruct
private property, but cannot because of private
access control. Similarly, the FooStruct
extension in Bar.swift
cannot extend and print privateStr
in Foo.swift
because FooStruct
is not contained in the same Swift file.
private
means declared code such as class
, struct
, enum
, property
and method
can only be accessed withing the current scope and enclosed type. Only extensions within the same Swift file can access private
declared code.
The scope of extension
can only access those private properties when they are declared in the same file of the extended, declared code (class
, struct
, enum
, property, or method, etc.).
fileprivate
struct FooStruct {
private let privateStr = "privateStr"
}
extension FooStruct {
func fooFunc() {
print("\(privateStr)")
}
}
Each Swift file can contain classes, structs, enums, etc. fileprivate
means the code can only be accessible within the same Swift file.
internal
is the default access control in the Swift language. Marking declared code as internal
means it can be accessed within the same module (app) freely. Developers can even subclass, extend, and override classes, structs, properties and methods.
public
Marking declared code as public
means that it can be accessed across different modules and files, but it cannot be subclassed. A good example is the init
function of a class in order to prevent abnormal initialization made by other developers.
open
The most unrestricted access control level. All open
declared code can be accessed and subclassed with no restriction among modules. The open
function and properties within the class can even be overriden.
For example, UICollectionView
is an open
class in that developers can create a custom UICollectionView
.
Summary
Access Control provides a great tool for developers to restrict access rights of declared code. It is useful when you are developing and SDK or API for other developers to implement. They include:
private
- Most restricted. Properties can only be accessed within the current enclosing type.fileprivate
- Can only be accessed within the same fileinternal
- This is the default access control and can be accessed within the same module freely.public
- Class can be accessed across different modules (app module and 3rd party library) but cannot be subclassed and its content cannot be overridden.open
- The most unrestricted access control and other developers can subclass it and override those open properties.
In order to develop a safe and stable app, it is recommended to consider private first, and then think twice before loosening up the access control.