SwiftUI DynamicPropertyプロパティラッパーの内部更新がビューの更新をトリガーすることを期待することは正しいですか?


10

SwiftUIでサポートされているカスタムプロパティラッパーを作成しようとしています。つまり、対応するプロパティ値を変更すると、SwiftUIビューが更新されます。ここに私が持っているものの簡単なバージョンがあります:

@propertyWrapper
public struct Foo: DynamicProperty {
    @ObservedObject var observed: SomeObservedObject

    public var wrappedValue: [SomeValue] {
        return observed.value
    }
}

ObservedObjectカスタムプロパティラッパー内に含まれている場合でも、SwiftUI SomeObservedObjectは次の限り変更をキャッチします。

  • 私のプロパティラッパーは構造体です
  • 私のプロパティラッパーは準拠しています DynamicProperty

残念ながらドキュメントはまばらで、これが現在のSwiftUI実装でうまくいかなかった場合にうまく機能しないかどうかを判断するのに苦労しています。

DynamicProperty(オンラインではなくXcode内の)のドキュメントは、そのようなプロパティが外部から変更されてビューを再描画するプロパティであることを示しているようですが、独自のタイプをこのプロトコルに準拠させたときに何が起こるかについては保証されません。

これが今後のSwiftUIリリースで引き続き機能することを期待できますか?


4
このトピックに何が期待されているかは明らかではありません...最後の質問に答えてください。誰かが「はい、確かに、あなたは期待できる」と答えたら本当に信じますか?))
Asperi

回答:


6

[OK]を...ここに同じようなことを取得するための代替的なアプローチである...しかし、構造体としてのみDynamicProperty巻き付け@State(力ビューのリフレッシュに)。

これは単純なラッパーですが、次のビューの更新でカスタム計算をカプセル化する可​​能性を提供します...と述べたように、値のみのタイプを使用します。

ここにデモがあります(Xcode 11.2 / iOS 13.2でテスト済み):

@StateのラッパーとしてのDynamicProperty

ここにコードがあります:

import SwiftUI

@propertyWrapper
struct Refreshing<Value> : DynamicProperty {
    let storage: State<Value>

    init(wrappedValue value: Value) {
        self.storage = State<Value>(initialValue: value)
    }

    public var wrappedValue: Value {
        get { storage.wrappedValue }

        nonmutating set { self.process(newValue) }
    }

    public var projectedValue: Binding<Value> {
        storage.projectedValue
    }

    private func process(_ value: Value) {
        // do some something here or in background queue
        DispatchQueue.main.async {
            self.storage.wrappedValue = value
        }
    }

}


struct TestPropertyWrapper: View {

    @Refreshing var counter: Int = 1
    var body: some View {
        VStack {
            Text("Value: \(counter)")
            Divider()
            Button("Increase") {
                self.counter += 1
            }
        }
    }
}

struct TestPropertyWrapper_Previews: PreviewProvider {
    static var previews: some View {
        TestPropertyWrapper()
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.