Daniel's working notes

Swift metatypes

struct Shop {
	let name: String
	func deactivate(by name: String) {}

let myShop: Shop = Shop()

We can get the metatype by using typeOf(Object)

If we use snippet above, we can call typeOf(myShop) //Shop.Type. Shop.Type is the metatype of Shop

Using typeOf we can access to all class properties and method, including init()

We can define metatype for structs, classes, enums and protocols.

type(of:) is dynamic metatypes while .self is static metatypes

static metatypes is to determine what is the compile time type of an object.

we use static metattypes in few places such as table view cell registration

tableView.register(MyTableViewCell.self, forReuseIdentifier: "myCell")

Protocol metatypes behave different than any other metatypes. Because it’s not referring to the protocol itself but to the metatype of whatever type that is conforming that protocol. Apple call this existensial metatype


If that sounds confusing, you can see it like this: Just like String is the type and "Hello World" is the value of an instance, String.Type is the type and String.self is the value of a metatype

On the other hand, type(of) will return a dynamic metatype, which is the metatype of the object’s real, runtime type.

let myNum: Any = 1 // Compile time type of myNum is Any, but the runtime type is Int.
type(of: myNum) // Int.type

The reason for that is that in the context of protocols, MyProtocol.Type doesn’t refer to the protocol’s own metatype, but the metatype of whatever type is inheriting that protocol. Apple calls this an existential metatype.

protocol MyProtocol {}
struct MyType: MyProtocol {}
let metaType: MyProtocol.Type = MyType.self

In this case, metatype only has access to MyProtocol class properties and methods, but MyType's implementations will be called. To get the concrete metatype of the protocol type itself, you can use the .Protocol suffix. That’s basically the same as using .Type on other types.

Linked Notes: