메타타입이란 타입의 타입이다. 클래스 타입의 타입과 구조체 타입의 타입, 열거형 타입, 프로토콜 타입의 타입도 메타타입이다.
어떤 클래스 SomeClass 의 메타타입은 SomeClass.Type 이다.
어떤 프로토콜 SomeProtocol 의 메타타입은 SomeProtocol.Protocol 이다.
어떤 타입에 .self 를 붙이면 해당 타입을 어떤 값으로써 접근할 수 있다.
예를들어, SomeClass.self 는 SomeClass의 인스턴스를 리턴하는게 아니라, SomeClass 라는 것 자체를 리턴한다(프로토콜도 마찬가지).
type(of:) 메소드는 인스턴스의 클래스를 리턴한다.
class SomeClass {
class func typeMethod(){
print("you've called type method")
}
static var typeProperty: String = "you've read type property"
}
var someInstance = SomeClass()
type(of: someInstance) // SomeClass.self
type(of: someInstance).typeMethod() // "you've called type method"
print(type(of: someInstance).typeProperty) // "you've read type property"
print(SomeClass.self.typeProperty) // "you've read type property"
print(SomeClass.typeProperty) // "you've read type property"
타입메소드나 타입프로퍼티에서 '타입'이라는 이름이 붙은 이유가 이것 때문이다. SomeClass.self는 SomeClass 와 같다.
이를 이용하면 컴파일때가 아니라 런타임때의 타입을 알 수 있다.
class SomeBaseClass {
class func printClassName() {
print("SomeBaseClass")
}
}
class SomeSubClass: SomeBaseClass {
override class func printClassName() {
print("SomeSubClass")
}
}
let someInstance: SomeBaseClass = SomeSubClass()
// The compile-time type of someInstance is SomeBaseClass,
// and the runtime type of someInstance is SomeSubClass
type(of: someInstance).printClassName()
// Prints "SomeSubClass"
type(of:) 메소드와 .self 를 이용해 AppDelegate 에서 view controller 를 다루는 예제.
let appDelegate: AppDelegate? = UIApplication.shared.delegate as? AppDelegate
if let controller = appDelegate?.window?.rootViewController {
if let navigationController: UINavigationController = controller as? UINavigationController {
let viewControllers: [UIViewController] = navigationController.viewControllers
for viewController in viewControllers {
if type(of: viewController) == SomeViewController.self {
print(viewController)
viewController.viewDidLoad()
}
if type(of: viewController) == OtherViewController.self {
print(viewController)
viewController.viewDidLoad()
}
}
프로젝트 내부의 view controller 들을 담은 배열 viewControllers를 만들고, if 문과 type(of:), .self 를 이용해 각 view controller 마다 다른 동작을 지시했다.
ref