読者です 読者をやめる 読者になる 読者になる

swift言語:Reflection APIを使ってみました

概要

swiftに含まれているReflection APIについて、The Swift Reflection API and what you can do with itを参考に、調べました。

ソースのコメントを見ると、PlaygroundやDebuggerなどで使うことが目的のようです。

$ cat ./stdlib/public/core/Mirror.swift
/// Mirrors are used by playgrounds and the debugger.

MirrorTypeも使えるようですが、使い方がわかりませんでした。

Reflection API

サンプルデータ

The Swift Reflection API and what you can do with itのサイトで説明に使っているデータです。

import Foundation.NSURL

public class Store {
    let storesToDisk: Bool = true
}
public class BookmarkStore: Store {
    let itemCount: Int = 10
}
public struct Bookmark {
    enum Group {
        case Tech
        case News
    }
    private let store = {
        return BookmarkStore()
    }()
    let title: String?
    let url: NSURL
    let keywords: [String]
    let group: Group
}

let aBookmark = Bookmark(title: "Appventure",
               url: NSURL(string: "appventure.me")!,
               keywords: ["Swift", "iOS", "OSX"], group: .Tech)

Mirror

Reflection APIを使うための最も簡単な方法は、Mirrorを作成することです。

// Mirror
let aMirror = Mirror(reflecting: aBookmark)
print(aMirror)
// Mirror for Bookmark

「Mirror for Bookmark」が出力されます。これは以下のメソッド定義によります。

$ cat ./stdlib/public/core/Mirror.swift
/// Reflection for `Mirror` itself.
extension Mirror : CustomStringConvertible {
  public var description: String {
    return "Mirror for \(self.subjectType)"
  }
}

Mirrorのメソッドは4つあります。

  • Mirror.displayStyle
  • Mirror.children
  • Mirror.subjectType
  • Mirror.superclassMirror:
Mirror.displayStyle

display styleを表示します。

print (aMirror.displayStyle)

Optional(Struct)が出力されます。データの型が出力されます。

public enum DisplayStyle {
    case Struct
    case Class
    case Enum
    case Tuple
    case Optional
    case Collection
    case Dictionary
    case Set
}
Mirror.children

child要素を一覧します。

for case let (label?, value) in aMirror.children {
    print (label, value)
}
Mirror.subjectType

型情報を出力します。

// subject type
print(aMirror.subjectType)
//prints : Bookmark
print(Mirror(reflecting: 5).subjectType)
//prints : Int
print(Mirror(reflecting: "test").subjectType)
//prints : String
print(Mirror(reflecting: NSNull()).subjectType)
//print : NSNull
Mirror.superclassMirror

スーパークラス情報を出力します。

// try our struct
print(Mirror(reflecting: aBookmark).superclassMirror())
// prints: nil
// try a class
print(Mirror(reflecting: aBookmark.store).superclassMirror())
// prints: Optional(Mirror for Store)

関連資料