期望SwiftUI DynamicProperty属性包装器的内部更新触发视图更新是否正确?


10

我正在尝试创建SwiftUI支持的自定义属性包装器,这意味着对相应属性值的更改将导致对SwiftUI视图的更新。这是我所拥有的简化版本:

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

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

我看到,即使my ObservedObject包含在我的自定义属性包装器中,SwiftUI仍然可以捕获更改,SomeObservedObject只要:

  • 我的属性包装器是一个结构
  • 我的属性包装器符合 DynamicProperty

不幸的是,文档稀疏,我很难说这是否只能通过当前的SwiftUI实现运气。

DynamicProperty(在Xcode中,不在在线中)的文档似乎表明这种属性是从外部更改的属性,导致视图重绘,但是无法保证将自己的类型与该协议兼容时会发生什么。

我可以期望它在以后的SwiftUI版本中继续工作吗?


4
目前尚不清楚该主题的期望是什么...最后一个问题的答案?您是否真的相信有人回答“是的,可以期待”?))
阿斯佩里

Answers:


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()
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.