SwiftUI DynamicProperty özellik sarmalayıcısının dahili güncellemelerinin bir görünüm güncellemesini tetiklemesini beklemek doğru mu?


10

SwiftUI tarafından desteklenen bir özel özellik sarıcı oluşturmaya çalışıyorum, yani karşılık gelen özellik değerlerinde değişiklik SwiftUI görünümde bir güncelleştirmeye neden olur. İşte sahip olduğumun basitleştirilmiş bir versiyonu:

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

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

Gördüğüm kadarıyla ObservedObjectbenim özel mülk sarmalayıcının içinde yer alsa bile, SwiftUI hala değişiklikleri SomeObservedObjectşu sürece yakalar :

  • Mülk sarmacım bir yapı
  • Mülk sarmalayıcıma uyuyor DynamicProperty

Ne yazık ki dokümanlar seyrek ve bunun sadece şu anki SwiftUI uygulamasıyla şanssız olup olmadığını söylemekte zorlanıyorum.

DynamicProperty(Xcode içinde, çevrimiçi değil) dokümanları, böyle bir mülkün, görünümün yeniden çizilmesine neden olan dışarıdan değiştirilen bir özellik olduğunu gösterir, ancak kendi türlerinizi bu protokole uyduğunuzda ne olacağının garantisi yoktur.

Bunun gelecekte SwiftUI sürümlerinde çalışmaya devam etmesini bekleyebilir miyim?


4
Bu konunun beklentisinin ne olduğu belli değil ... son soruya cevap? Birisinin "evet, tabii ki bekleyebilirsiniz" cevabına gerçekten inanır mısın? ))
Asperi

Yanıtlar:


6

Tamam ... benzer bir şey elde etmek için alternatif bir yaklaşım var ... ama yapı sadece DynamicPropertyetrafına sarılmış olarak @State(görünüm yenilemeyi zorlamak için).

Basit bir sarıcıdır, ancak aşağıdaki görünüm yenilemesiyle ve yalnızca değer türlerini kullanarak herhangi bir özel hesaplamayı kapsama olanağı sağlar.

İşte demo (Xcode 11.2 / iOS 13.2 ile test edilmiştir):

@State'te sarmalayıcı olarak DynamicProperty

İşte kod:

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()
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.