LoginSignup
25
19

More than 3 years have passed since last update.

SwiftUI Property WrappersクラスのwrappedValue・projectedValue一覧表

Last updated at Posted at 2019-09-20

環境

Swift 5.1
Xcode 11.0 (11A420a)

2019年9月現在SwiftUIは変化が大きく、当記事に示した挙動もバージョンを経ると変更される可能性が十分にあるため、ご注意ください。

執筆動機

Swift5.1にてProperty Wrappersという機能が追加されました。
ですが当方、foo_foo$foowrappedValueprojectedValueがそれぞれ何を意味しているのか...と、
それぞれの関係性が掴みあぐねておりまして...😇

ですが、先日のこちら(YouTubeに遷移します)の発表とその資料で非常に丁寧に解説されており、自分でも手を動かすことで、理解を深めることができました。
複雑に考えすぎていたのですが、その実態はすごくシンプルだったんですね...。😅

すなわち。ほぼ引用してしまう形ですが...。

1.

@Hoge var foo: Int 

と書くと、

var foo: Int
var _foo: Hoge<Int>

に展開されるような形となる。

2.

foo _foo.wrappedValue と等価
$foo _foo.projectedValue と等価

ルールとしてはたったこれだけでした。

例えばHogeクラスが、このような定義で、いまelementInt42 が入っていて...

// @propertyWrapperは、クラス・構造体・列挙体に付加可能
@propertyWrapper
struct Hoge<T> {
    var element: T  // 今、ここが :Int = 42 だとする

    // これはgetterのみ定義しているが、望むならsetterを定義することも可能
    var wrappedValue: T { element }
    // これはgetterのみ定義しているが、望むならsetterを定義することも可能
    var projectedValue: Hoge<T> { Hoge(element: element) }
}

このようなプロパティがあるとしたら...

// ここの型アノテーションは、移譲先の型の wrappedValueの型と一致しなければならない
// 一致しないときは、Property type '誤って指定した型名' does not match that of the 'wrappedValue' property of its wrapper type 'wrappedValueの型' というコンパイルエラーが出力される
@Hoge var foo: Int 

foo と書くと、wrappedValue のgetter呼び出し

print(foo)の結果
42

$fooと書くと、projectedValue のgetter呼び出し

print($foo)の結果
Hoge<Int>(element: 42)

になります。

wrappedValue にアクセスするには、

  • foo
  • _foo.wrappedValue

projectedValue にアクセスするには、

  • $foo
  • _foo.projectedValue

それぞれ2通りの方法がある、ということですね。
後者は冗長な書き方ということになると思うので、基本的に前者の書き方でアクセスしていけばいいかと思います。

SwiftUI Property WrappersクラスのwrappedValue、projectedValue一覧表

ということで、SwiftUIで頻出するProperty WrappersクラスのwrappedValueprojectedValueが返す値の型をまとめ、表に起こしてみました。

propertyWrapperクラス wrappedValue projectedValue
State<Value> Value { get nonmutating set } Binding<Value> { get }
Binding<Value> Value { get nonmutating set } Binding<Value> { get }
ObservedObject<ObjectType> ObjectType { get } ObservedObject<ObjectType>.Wrapper { get }
EnvironmentObject<ObjectType> ObjectType { get } EnvironmentObject<ObjectType>.Wrapper { get }
Environment<Value> Value { get } × (未定義のためコンパイルエラー)

参考

Why I Can Mutate @State var? How Does @State Property Wrapper Work Inside?

25
19
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
25
19