この記事の要点
- property wrapper は Swift 5.1 で導入された、プロパティのアクセスにまつわる共通パターン(バリデーション・変換・永続化など)を再利用しやすくするための仕組みです。その後、ローカル変数や関数・クロージャの引数でも使えるように拡張されてきました。
- この記事自体は新機能の発表ではなく、コミュニティの優れた 解説記事・トーク・パッケージ を紹介するキュレーション記事です。property wrapper を学んだり、実プロジェクトへ取り入れたりする際の入り口として使えます。
- property wrapper は、振る舞いの「契約」を 利用箇所ではなく宣言箇所 で指定できる点が利点です。ボイラープレートを取り除き、
@Settingのような短い注釈だけで定型処理を表現できます。
property wrapper とは
property wrapper は、プロパティの読み書きに共通して現れる処理を、独立した型としてまとめて再利用できるようにする機能です。Erica Sadun のトーク(dotSwift 2020)では、property wrapper の価値が「振る舞いの契約を、プロパティの 利用箇所 ではなく 宣言箇所 で指定できること」にあると説明されています。たとえば「この値は常に特定の範囲に収める」「この値は永続化する」といった約束を、プロパティ定義の場所に一度書くだけで表現できます。
property wrapper には大きく 2 つの値が関わります。
- wrapped value:
@MyWrapper var xとしたときのxそのもの。通常のプロパティと同じようにアクセスする値です。 - projected value:
$xでアクセスできる補助的な値。wrapped value とは別に、property wrapper が公開したい追加情報や操作を提供します。
Stewart Lynch のトークでは、この wrapped value と projected value の両方が、UIKit と SwiftUI のそれぞれでどう役立つかが具体的に示されています。
何ができるのか
property wrapper の主な効果は、繰り返し現れる定型処理を取り除き、コードを簡潔にする ことです。記事で紹介されているコミュニティの解説では、次のようなテーマが扱われています。
- property wrapper の初期化方法と projected value の仕組み(Sarun Wongpatcharapakorn)
- 繰り返しの処理をカスタム property wrapper に置き換えてボイラープレートを減らす方法(Antoine van der Lee)
- デバイスの向きを追跡する property wrapper を作る実例(Rudrank Riyam)
SwiftUI 向けには、DynamicProperty プロトコルを使ってカスタム property wrapper を書く方法も紹介されています(Donny Wals)。DynamicProperty に適合させると、SwiftUI のビュー更新の仕組みと連動する property wrapper を自作でき、たとえば次のように簡潔なコードが書けます。
struct ContentView: View {
@Setting(\.onboardingCompleted) var didOnboard
var body: some View {
Text("Onboarding completed: \(didOnboard ? "Yes" : "No")")
Button("Complete onboarding") {
didOnboard = true
}
}
}
ここでは @Setting というカスタム property wrapper が、設定値の読み書き(永続化など)を内部に隠しています。ビュー側は didOnboard を普通の Bool のように読み書きするだけで済み、設定ストアへのアクセスといった定型処理がコードから消えます。
活用とパッケージ
property wrapper をゼロから書かなくても、既存のパッケージを利用できます。記事では次の 2 つが挙げられています。
- ValidatedPropertyKit(Sven Tiigi): 文字列が特定の正規表現に一致するか、シーケンスが所定の要素数を持つか、数値が特定の範囲に収まるか、といったバリデーションを property wrapper で表現できます。
- Burritos(Guillermo Muntaner):
@Clamping・@Expirable・@Trimmedなど、すぐ使えるサンプル property wrapper を集めたライブラリです。自作の参考にもなります。
これらを使うと、バリデーションや値の正規化といった処理を、宣言箇所の注釈だけで適用できます。
関連リンク
- SE-0258: Property Wrappers — property wrapper を Swift 5.1 に導入した Proposal
- ValidatedPropertyKit — バリデーション用 property wrapper のライブラリ
- Burritos — サンプル property wrapper を集めたライブラリ