- Access control restricts access to parts of your code from code in other source files and modules.
- This feature enables you to hide the implementation details of your code, and to specify a preferred interface through which that code can be accessed and used.
- You can assign specific access levels to individual types (
classes
,structures
, andenumerations
), as well as toproperties
,methods
,initializers
, andsubscripts
belonging to those types.Protocols
can be restricted to a certain context, as canglobal constants
,variables
, andfunctions
.
Modules and Source Files
- Swift’s
access control
model is based on the concept of modules and source files. - 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. - Each build target (such as an app bundle or framework) in Xcode is treated as a separate module in Swift.
- If you group together aspects of your app’s code as a stand-alone framework—perhaps to encapsulate and reuse that code across multiple applications—then everything you define within that framework will be part of a separate module when it’s imported and used within an app, or when it’s used within another framework.
Access Levels
- Swift provides five different access levels for entities within your code.
- These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.
1. open — least restrictive
-
Enable an
entity
to be used outside the defining module (target). You typically useopen
orpublic
access when specifying the public interface to a framework. -
Let’s consider an example:
UIKit
. We often use many UI elements fromUIKit
daily. When you try to use theUIComponents
such asUIButton
,UICollectionView
,UITableView
,UIViewController
etc.., you have toimport
theUIKit
on the top. SoUIKit
is actually a module that we can import to our class and subclass its features.
import UIKit
class BobbyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("hello")
}
}
let obj = BobbyViewController()
obj.viewDidLoad()
/* prints
hello */
viewDidLoad
is a function that is marked withopen
. You even have the ability to override it.
2. public
- Like
open
access level,public
access level enable an entity to be used outside the defining module (target). But open access level allows us to subclass it from another module where in public access level, we can only subclass or overridde it from within the module it is defined.
// RandomLibraryFromGithub
public func A() {}
open func B() {}
// In your current project
override func A(){} // error
override func B(){} // success
3. internal
internal
is the default access level.- Internal classes and members can be accessed anywhere within the same module(target) they are defined.
- You typically use internalaccess when defining an app’s or a framework’s internal structure.
class Test1{
internal var a = 30
var b = 50
init() {
print("value of a and b",a,b)
}
}
class Test2: Test1{
let obj1 = Test1()
// Uncomment next lines and it will show error unauthorized access
// obj1.a = 40
// obj1.b = 90
}
let obj2 = Test2()
/* reults:
value of a and b 30 50
value of a and b 30 50
*/
4. 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. ie; the functionality defined with afileprivate
access level can only be accessed from within the swift file where it is defined.
// NewViewController.swift
fileprivate class NewViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
// ViewController.swift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// uncommenting next line will show an error as class is defined as fileprivate
// let newViewController = NewViewController()
let bobbyViewController = BobbyViewController()
bobbyViewController.viewDidLoad()
}
}
let viewController = ViewController()
viewController.viewDidLoad()
/* prints:
hello */
5. private — most restrictive
Private
access restricts the use of an entity to the enclosing declaration, and to extensions of that declaration that are in the same file.- 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.
class Game {
private var number = 0
func score() {
print(number)
}
func increaseNumberByOne() {
number += 1
}
}
//uncommenting next line will show an error of inaccesibility
//Game().number
Game().score()
//prints: 0
- 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.
class MyClass: UIViewController{
private var myClassVarA = 90
override func viewDidLoad() {
super.viewDidLoad()
print("private variable:",myClassVarA)
}
}
extension MyClass{
func printValueOfA(){
print("accessing private variable of same class in extension:",myClassVarA)
}
}
let myClassObj = MyClass()
myClassObj.viewDidLoad()
myClassObj.printValueOfA()
/* prints:
private variable: 90
accessing private variable of same class in extension: 90 */
Next - Enum (Enumerations) by Example