在需要@Binding的地方传递@Published(SwiftUI,Combine)

Ric*_*hiy 7 data-binding binding publisher swiftui combine

一个ViewModel类有一个sourceProperty正在由 编辑的TextField。该属性是@Published. 我想将它Logic传递给具有Binding<String>. 该类将监听更改sourceProperty,对其做出反应并将其输出设置为属性@Published output

如何@Published sourceProperty作为初始化参数传递给类Logic

相关代码:

final class ViewModel {
    @Published var sourceProperty: String = ""
    private var logic: Logic?

    init() {
        self.logic = Logic(data: $sourceProperty)
        $logic.output.sink({result in 
            print("got result: \(result)")
        })
    }

}

final class Logic: ObservableObject {
    private var bag = Set<AnyCancellable>()
    @Published var output: String = ""
    @Binding var data: String
    init(data: Binding<String>) {
        self._data = data

        $data.sink({ newValue in 
            output = newvalue + "ABCDE"
        }).store(in: &bag)
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止我收到以下错误:

无法将“Published.Publisher”类型的值转换为预期的参数类型“Binding”

目标是使用对象自身属性的更改来触发另一个对象中的方法调用,然后将该第二个对象的输出绑定到某个视图。

视图层:

public struct ViewLayer: View {
    @Binding private var sourceProperty: String

    public init(_ placeholder: String,
                sourceProperty: Binding<String>,
    ) {
        self.placeholder = placeholder
        self._sourceProperty = sourceProperty
    }

    public var body: some View {
        TextField(placeholder, text: $sourceProperty)
    }

 }
Run Code Online (Sandbox Code Playgroud)

LuL*_*aGa 9

如果我正确理解你的问题,你可能正在寻找类似的东西:

final class ViewModel: ObservableObject {
    
    @Published var sourceProperty: String = ""
    private lazy var logic = Logic(data: $sourceProperty)
    private var cancellable: AnyCancellable?

    init() {
        cancellable = logic.$output
            .sink { result in
                print("got result: \(result)")
            }
    }

}

final class Logic: ObservableObject {
    
    @Published private(set) var output: String = ""
    
    init(data: Published<String>.Publisher) {
        data
            .map { $0 + "ABCDE" }
            .assign(to: &$output)
    }
}
Run Code Online (Sandbox Code Playgroud)