如何实现自定义属性包装器,该包装器将发布更改以供SwiftUI重新呈现其视图

时间:2020-01-25 18:54:12

标签: swift swiftui property-wrapper

尝试实现自定义属性包装,该包装也将以与@Publish相同的方式发布其更改。 例如。允许我的SwiftUI使用自定义包装器接收对属性的更改。

我拥有的工作代码:

import SwiftUI

@propertyWrapper
struct MyWrapper<Value> {
    var value: Value

    init(wrappedValue: Value) { value = wrappedValue }

    var wrappedValue: Value {
        get { value }
        set { value = newValue }
    }
}

class MySettings: ObservableObject {
    @MyWrapper
    public var interval: Double = 50 {
        willSet { objectWillChange.send() }
    }
}

struct MyView: View {
    @EnvironmentObject var settings: MySettings

    var body: some View {
        VStack() {
            Text("\(settings.interval, specifier: "%.0f")").font(.title)
            Slider(value: $settings.interval, in: 0...100, step: 10)
        }
    }
}

struct MyView_Previews: PreviewProvider {
    static var previews: some View {
        MyView().environmentObject(MySettings())
    }
}

但是,我不喜欢需要为objectWillChange.send()类中的每个属性调用MySettings

@Published包装器运行良好,因此我尝试将其实现为@MyWrapper的一部分,但未成功。

我发现一个不错的灵感来自https://github.com/broadwaylamb/OpenCombine,但即使尝试从那里使用代码,我也失败了。

在执行过程中遇到困难时, 我意识到,为了使@MyWrapper正常工作,我需要准确地了解@EnvironmentObject@ObservedObject如何订阅@Published的更改。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:4)

在实施https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type之前,我想出了以下解决方案。

通常,我会使用反射将objectWillChange的{​​{1}}引用传递给所有用MySettings注释的属性。

@MyWrapper