As of Swift 3.0.1, there are 4 levels of access, described below from the highest (least restrictive) to the lowest (most restrictive).
1. open and public
Enable an entity to be used outside the defining module (target). You typically use open or public access when specifying the public interface to a framework.
However, open access applies only to classes and class members, and it differs from public access as follows:
public classes and class members can only be subclassed and overridden within the defining module (target). open classes and class members can be subclassed and overridden both within and outside the defining module (target).
// First.framework – A.swift open class A {}
// First.framework – B.swift public class B: A {} // ok
// Second.framework – C.swift import First internal class C: A {} // ok
// Second.framework – D.swift import First internal class D: B {} // error: B cannot be subclassed
2. internal
Enables an entity to be used within the defining module (target). You typically use internal access when defining an app’s or a framework’s internal structure.
// First.framework – A.swift internal struct A {}
// First.framework – B.swift A() // ok
// Second.framework – C.swift import First A() // error: A is unavailable
3. fileprivate
Restricts the use of an entity to its defining source file. You typically use fileprivate access to hide the implementation details of a specific piece of functionality when those details are used within an entire file.
// First.framework – A.swift internal struct A { fileprivate static let x: Int } A.x // ok
// First.framework – B.swift A.x // error: x is not available
4. private
Restricts the use of an entity to its enclosing declaration. You typically use private access to hide the implementation details of a specific piece of functionality when those details are used only within a single declaration.
// First.framework – A.swift internal struct A { private static let x: Int internal static func doSomethingWithX() { x // ok } } A.x // error: x is unavailable