// metatype of a (class, struct, enum) typeSomeType.Type// metatype of a protocolSomeProtocol.Type
A metatype type refers to the type of any type, including class types, structure types, enumeration types, and protocol types.
The dynamic type (runtime type) returned from type(of:) is a concrete metatype (T.Type) for a class, struct, enum, or other nonprotocol type T, or an existential metatype (P.Type) for a protocol or protocol compositionP. ๐1๏ธ2๏ธ
When the static type (compile-time type) of the value passed to type(of:) is constrained to a class or protocol, you can use that metatype to access initializers or other static members of the class or protocol. ๐1๏ธ3๏ธ
Use an initializer expression to construct an instance of a type from that typeโs metatype value. ๐3๏ธ4๏ธ
For class instances, the initializer thatโs called must be marked with required or the entire class marked with final. ๐4๏ธ
(the compiler must make sure the initializer is implemented by every possible subtype of the type)
// base classclassA {classvar className: String { "A" } // โญ๏ธ static member}// subclassclassB:A {overrideclassvar className: String { "B" }}let obj: A =B()// โญ๏ธ compile-time type: A// โญโโโโโโโโโโโโฎ โ โญ๏ธ runtime type as a valuetype(of: obj).className // โญ๏ธ runtime type: B
// parameter `value`funcprintInfo(_value: Any) { // โญ๏ธ static : Anylet t =type(of: value)// โญ๏ธ dynamic: Intprint("'\(value)' of type '\(t)'")}// constant `count`let count: Int=5// static: Int, dynamic: Int (same)printInfo(count)
extensionVector2D {/// convert one conforming type to another type /// with the **same vector field**.////// Example:/// ```/// let u = CGPoint(x: 1, y: 2)/// u.as(CGSize.self) // โญ๏ธ `CGSize.self`: access type as a value/// ```// โญ๏ธ โญโ1โโฎ โญโ2โโโฎpublicfunc`as`<T:Vector2D>(_typeT: T.Type) -> T where T.Field == Self.Field {// โญโโโโโโโโ 3 โโโโโโโโโโฎreturn typeT.init(x: x, y: y) }}// โญ๏ธ 1. parameter (type T as a value)// โญ๏ธ 2. metatype of type T// โญ๏ธ 3. initializer expresssion
// subclass of AclassC:A {let name: Stringrequiredinit(name: String) { // โญ๏ธ marked with `required` self.name = name }overrideclassvar className: String { "C" }}// โญโ1โโโฎ โญโ2โโโฎlet typeC: C.Type= C.self// โญ๏ธ 1. metatype of type `C`// โญ๏ธ 2. access type `C` as a value// โญ๏ธ initializing from a metatype value must reference 'init' explicitly// โญโโโโโโโโ 3 โโโโโโโโโโฎlet obj = typeC.init(name:"hi")// type C's instance// โญ๏ธ 3. initializer expresssion
iOS 15 Programming Fundamentals with Swift (2021) - Type Reference, p.187 โญ๏ธ