Чи правильно очікувати внутрішніх оновлень обгортки властивості 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
Незрозуміло, чого очікує ця тема ... відповідь на одне останнє запитання? Ви дійсно вірите, якщо хтось відповість «так, впевнено, ви можете сподіватися»? ))
Аспер

Відповіді:


6

Гаразд ... ось альтернативний підхід, щоб отримати подібну річ ... але як структура лише DynamicPropertyобгорнута @State(щоб змусити оновлення перегляду).

Це проста обгортка, але дає можливість інкапсулювати будь-які спеціальні обчислення з наступним оновленням перегляду ... і, як було сказано, використовуючи типи, що мають значення лише

Ось демонстрація (тестована з Xcode 11.2 / iOS 13.2):

DynamicProperty як обгортка на @State

Ось код:

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()
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.