125 Views
August 10, 23
スライド概要
YUMEMI.grow Mobile #6 - connpass
https://yumemi.connpass.com/event/290375/
YUMEMI.grow Mobile #6 - YouTube
https://www.youtube.com/watch?v=gNd-3YjaUwg
@ViewLoadingプロパティラッパの紹介と自前で実装する方法
https://zenn.dev/yumemi_inc/articles/viewloading-property
@ViewLoadingプロパティラッパを自前で実装する方法について話しました #yumemi_grow - usami-kの日記
https://usami-k.hatenablog.com/entry/2023/08/10/214536
https://usami-k.github.io/
@ViewLoadingプロパティラッパの 紹介と自前で実装する方法 宇佐見公輔 / 株式会社ゆめみ 2023-08-10 @ViewLoadingプロパティラッパの紹介と自前で実装する方法 1
自己紹介 宇佐見公輔(うさみこうすけ) 株式会社ゆめみ / iOSテックリード 大阪在住 iOSDC Japan 2023 パンフレット記事を執筆しました 現地参加予定 @ViewLoadingプロパティラッパの紹介と自前で実装する方法 2
今日の内容 @ViewLoading @ViewLoading プロパティラッパの紹介 を自前で実装する方法 @ViewLoadingプロパティラッパの紹介と自前で実装する方法 3
@ViewLoading プロパティラッパの紹介 @ViewLoadingプロパティラッパの紹介と自前で実装する方法 4
@ViewLoading とは iOS 16.4で追加された 2023年3月リリース マイナーアップデートでのSDKの機能追加はめずらしい のプロパティが扱いやすくなる UIViewController @ViewLoadingプロパティラッパの紹介と自前で実装する方法 5
UIViewController のプロパティ class DateViewController: UIViewController { private var dateLabel: UILabel! // Optional 型 override func viewDidLoad() { super.viewDidLoad() let label = UILabel(frame: self.view.bounds) self.view.addSubview(label) self.dateLabel = label } } (このコード例はAppleのドキュメントから引用) @ViewLoadingプロパティラッパの紹介と自前で実装する方法 6
UIViewController のプロパティ class DateViewController: UIViewController { private var dateLabel: UILabel! // Optional 型 一度設定したら にならないのでOptional型は冗長に感じる しかし、非Optional型にする場合は初期化時に値の設定が必要 時に値を設定するにはOptional型にする必要がある nil viewDidLoad() @ViewLoadingプロパティラッパの紹介と自前で実装する方法 7
@ViewLoading プロパティラッパ class DateViewController: UIViewController { @ViewLoading private var dateLabel: UILabel // 非Optional型 override func viewDidLoad() { super.viewDidLoad() let label = UILabel(frame: self.view.bounds) self.view.addSubview(label) self.dateLabel = label } } @ViewLoadingプロパティラッパの紹介と自前で実装する方法 8
@ViewLoading プロパティラッパ class DateViewController: UIViewController { @ViewLoading private var dateLabel: UILabel // 非Optional型 非Optional型で宣言できる 内部的にはOptional型で値を持っている アクセス時に内部の値をunwrapして返してくれる → アクセス時にまだ値が設定されていなかったら? get @ViewLoadingプロパティラッパの紹介と自前で実装する方法 9
@ViewLoading プロパティラッパ アクセス時にViewのロードを行ってくれる アクセス時 → が実行される → が実行される → プロパティの値が返される このため、 でプロパティの値を設定すれば良い get get loadView() viewDidLoad() viewDidLoad() @ViewLoadingプロパティラッパの紹介と自前で実装する方法 10
注意点 で値を設定し忘れると実行時エラーになる のunwrapになってしまうため プロパティラッパを指定したプロパティは、必ず で値を設定すること viewDidLoad() nil @ViewLoading viewDidLoad() @ViewLoadingプロパティラッパの紹介と自前で実装する方法 11
利用例 class DateViewController: UIViewController { var date: Date? { didSet { guard let date else { return } let dateString = self.dateFormatter.string(from: date) self.dateLabel.text = dateString } } } let dateViewController = DateViewController() dateViewController.date = Date() @ViewLoadingプロパティラッパの紹介と自前で実装する方法 12
利用例 var date: Date? { didSet { self.dateLabel.text = dateString } } の の中で にアクセスしている この時点で の値が設定されている必要がある date didSet dateLabel dateLabel @ViewLoadingプロパティラッパの紹介と自前で実装する方法 13
利用例 let dateViewController = DateViewController() dateViewController.date = Date() へのアクセス時点ではViewのロードが行われていない このため について を使っていない場合はエラーになる を使っている場合は正常に動作する date dateLabel @ViewLoading @ViewLoading @ViewLoadingプロパティラッパの紹介と自前で実装する方法 14
@ViewLoading を自前で実装する方法 @ViewLoadingプロパティラッパの紹介と自前で実装する方法 15
@ViewLoading を古いOSでも使いたい 便利な機能だがiOS 16.4以降でしか使えない それ以前のバージョンで使うために自前で実装することを考える @ViewLoadingプロパティラッパの紹介と自前で実装する方法 16
@ViewLoading を自前で実装する プロパティラッパはSwiftの機能であり自作できる しかし の実現は通常の方法ではどうも難しい とくに のメソッドを呼ぶ手段がわからない リファレンス実装を作っている人がいたので参考にする https://github.com/danielpunkass/MagicLoading @ViewLoading UIViewController @ViewLoadingプロパティラッパの紹介と自前で実装する方法 17
プロパティラッパの通常の実装方法 @propertyWrapper struct TwelveOrLess { private var number = 0 var wrappedValue: Int { get { return number } set { number = min(newValue, 12) } } } を実装する このプロパティを含む構造体やクラスからは独立している wrappedValue @ViewLoadingプロパティラッパの紹介と自前で実装する方法 18
プロパティラッパの第二の実装方法
@propertyWrapper
struct MagicViewLoading<Value> {
static subscript<T>(
_enclosingInstance instance: T,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<T, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<T, Self>
) -> Value {
...
}
}
@ViewLoadingプロパティラッパの紹介と自前で実装する方法
19
プロパティラッパの第二の実装方法 この実装方法なら、プロパティを含むクラスにアクセスできる この実装方法はSwiftのドキュメントには記載されていない プロポーザルには記載がある swift-evolution SE-0258 Property Wrappers Swift by Sundellで紹介されている Accessing a Swift property wrapper’s enclosing instance | Swift by Sundell @ViewLoadingプロパティラッパの紹介と自前で実装する方法 20
@ViewLoading
の実装
static subscript<T: UIViewController>(
_enclosingInstance instance: T,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<T, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<T, Self>
) -> Value {
get {
instance.loadViewIfNeeded()
return instance[keyPath: storageKeyPath].stored!
}
set {
instance[keyPath: storageKeyPath].stored = newValue
}
}
@ViewLoadingプロパティラッパの紹介と自前で実装する方法
21
まとめ iOS 16.4で という便利機能が追加された それ以前のバージョンでも同様の機能の実現が可能 ただしSwiftのドキュメントに記載されていない方法なので注意 @ViewLoading @ViewLoadingプロパティラッパの紹介と自前で実装する方法 22