LoginSignup
8
7

この記事は何?

Swift 5.9から導入されたマクロについて、Appleの開発者向けドキュメントより「Applying Macro」を独自に解説する。

マクロは、コンパイル時に定型的に繰り返されるコードを生成する。

Swiftを基礎から学ぶには
自著、工学社より発売中の「まるごと分かるSwiftプログラミング」をお勧めします。変数、関数、フロー制御構文、データ構造はもちろん、構造体からクロージャ、エクステンション、プロトコル、クロージャまでを基礎からわかりやすく解説しています。

概要

Swiftマクロは、コンパイル時にソースコードを部分的に生成するので、Swiftで反復的なコード記述を減らすことができる。
マクロの呼び出しは常に追加的に行われる。
マクロは、元のコードに新しいコードを追加するが、すでにプロジェクトの一部であるコードを変更したり、削除したりしない。

Swift標準ライブラリや多くのフレームワークは、多くのマクロを提供する。
独自のマクロを書くこともできる。

マクロはSwiftコードを生成するため、コードがマクロを使用するかどうかに関係なく、開発とデバッグに同じツールを使用すること。

マクロ展開の概要を示す図
image.png
左側は「元のSwiftコード」だけだが、右側には「マクロによって追加されたコード」がある。

マクロを呼び出す

マクロを呼び出す方法は、マクロを「宣言にアタッチ(添付)するかどうか」によって多少、異なる。

マクロを「宣言にアタッチする」には、マクロ名の先頭にアットマーク記号@をつけて、その直後にマクロ引数を指定する。
これは、属性を書くのと同じ構文。

添付マクロの呼び出し
@Observable class MyObject {
    public var someProperty: String = ""
    public var someOtherProperty: Int = 0
    fileprivate var somePrivateProperty: Int = 1
}

宣言にアタッチされたマクロはコードを生成して、そのコードを宣言に追加する。
たとえば、上記のObservable()マクロは、MyObjectクラスにメンバーを追加してObservableプロトコルを採用して、MyObjectObservableに準拠する。

宣言にアタッチせずにマクロを呼び出すには、マクロ名にシャープ記号#をつけて、その直後にマクロ引数を指定する。
これは、#ifやその他のコンパイル時操作と同じ構文。

自立マクロの呼び出し
let messagePredicate = #Predicate<Message> { message in
    message.recipient == "John Appleseed"
}

宣言に添付されていないマクロはコードを生成し、マクロを呼び出す場所にそのコードを追加する。
たとえば、上記のコードの#Predicateマクロは、Predicate構造体のインスタンスを作成する。

Predicate型のドキュメントはこちら

マクロの詳細については、Swiftプログラミング言語を参照。

展開したマクロのコードを見る

プロジェクトをビルドすると、Swiftはコードを読み、マクロを呼び出す場所を探す。
その後、Swiftは各マクロの実装を呼び出して、コードを展開する。
最後に、Swiftは生成されたコードを含め、通常どおりプロジェクトをビルドする。

Xcodeでマクロが生成したコードを表示するには、マクロを呼び出すコードをクリックし、「Editor > Expand Macro」を選択する。
展開したコードを読んで「マクロの動作の詳細」を理解することができる。
また、拡張コードを使用してマクロを使用するコードをデバッグすることができる。
マクロによって生成されたコードにブレークポイントを設定することも可能。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7