合并:初始化变异“自我”参数

时间:2020-01-23 03:23:11

标签: ios swift swiftui combine

我正在弄混组合代码和Swift UI,并遇到了这个问题。实际上,我想将Publisher传递到View中,并在发布者每次发布更新时都更新View

这是一个无法编译的示例游乐场。相反,它在Escaping closure captures mutating 'self' parameter行上出现错误- .sink(...

import Combine
import SwiftUI

struct MyView: View {

    let cancellable: AnyCancellable
    @State var current: Int = 0

    init<P>(publisher: P) where P: Publisher, P.Output == Int, P.Failure == Never {
        cancellable = publisher.sink { value in
            self.current = value
        }
    }

    var body: some View {
        Text("\(current)")
    }
}

let subject = PassthroughSubject<Int, Never>()
let x = MyView(publisher: subject)
subject.send(5)

当前,我已更改代码以使用内部带有值的ObservableObject视图模型,并告诉该对象发送更新。但是我很感兴趣其他人如何解决这个问题,因为我也想要一个无视图模型选项。

你们做了什么?

2 个答案:

答案 0 :(得分:5)

您可以使用onReceive来订阅SwiftUI Publisher中的Combine View。这样,即使您的视图可能被多次重新创建,SwiftUI运行时也将为您管理预订。

struct MyView: View {
    @State var current: Int = 0

    var body: some View {
        Text("\(current)")
            .onReceive(somePublisher) { self.current = $0 }
    }
}

但是,直接使用ObservableObject通常是更好的主意,因为它们直接集成到SwiftUI中。

答案 1 :(得分:0)

目前我正在做这样的事情:

import Combine
import SwiftUI
import PlaygroundSupport

class Model: ObservableObject {
    var current: Int = 0 {
        willSet {
            self.objectWillChange.send()
        }
    }
}

struct MyView: View {

    @EnvironmentObject var model: Model

    var body: some View {
        Text("\(model.current)")
    }
}

let model = Model()
let myView = MyView().environmentObject(model)
PlaygroundPage.current.liveView = UIHostingController(rootView: myView)

model.current = 5