Metatypes in Swift
Why .self and .type matter
--
Before we start
Difficulty: Beginner | Easy | Normal | Challenging
Keywords and Terminology:
Metatypes: the type of any type
Prerequisites:
- None
Why
In Swift, you might have noticed that some code uses .self
and some uses .type
for various uses which can seem rather opaque to the beginner.
These are useful, and should not simply be ignored however!
A Simple example
You might have a rather forced example as follows:
struct Person{
var name: String
init(_ name: String) {
self.name = name
}
}
let tina = Person("Tina")
so tina is clearly an instance of Person
.
We can see this with the following print statements:
print(tina.self) // Person(name: "Tina")
print(type(of: tina)) // Person
The overview
Each instance of Person
can be represented by two things, the Type of the metatype.
Type: Person
Metatype: Person.Type
The Type here represents the type of an instance, but the Metatype represents the metatype, which is a type that describes another type. In other words, the metatype describes the structure and properties of the type (including methods and properties) but does not describe the actual values.
When a function needs a type
So if you are writing a function that accepts a type (i..e Person.Type) rather than an instance you can write Person.Type as the type of the parameter — and that parameter would be Person.self.
A common use of self is from the register function in tableview:
tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "MyTableViewCell")
where the register function itself asks for any class with the definition:
func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String)