【问题标题】:Why are nested publishers not calling my custom Publishers in SwiftUI/Combine?为什么嵌套发布者没有在 SwiftUI/Combine 中调用我的自定义发布者?
【发布时间】:2021-01-01 19:42:02
【问题描述】:

这是How to share published model between two view models in SwiftUI? 的后续问题。

为了使嵌套发布模型真正发布,我使用了这里描述的方法:How to tell SwiftUI views to bind to nested ObservableObjects。到目前为止一切顺利,手动 objectWillChange 传递有效,并且更改由父视图模型发布。

但是,如果我尝试使用自定义发布者,它利用已发布的嵌套模型,它们就不会像我习惯的那样运行(使用常规发布的属性)。这是一个简化的例子。

我错过了什么吗?

import SwiftUI
import Combine

struct ContentView: View {
    @StateObject var contentViewModel = ContentViewModel()
    var body: some View {
        VStack{
            // Both toggle together, indicating that objectWillChange works correctly
            ModelEditView(model: contentViewModel.model)
            ModelEditView(model: contentViewModel.model)
            // This toggle binds another not nested published property
            Toggle("Not Nested Toggle", isOn: $contentViewModel.isToggled)
            // Custom toggleChangedPublisher only works with the not nested property
            Text(contentViewModel.internalChangedValue ? "true" : "false")
        }
    }
}

class Model: ObservableObject {
    @Published var nestedIsToggled = false
}

class ContentViewModel: ObservableObject {
    //Nested Model
    @Published var model = Model()
    //Not nested model equivalent
    @Published var isToggled = false
    //Property only altered by the custom toggleChangedPublishers
    @Published var internalChangedValue = false
    
    var anyCancellables = Set<AnyCancellable>()
    
    init() {
        // This should notify the "parent" ContentViewModel of changes in nested model
        anyCancellables.insert(model.objectWillChange.sink { [weak self] (_) in
            self?.objectWillChange.send()
        })
        nestedToggleChangedPublisher
            .receive(on: RunLoop.main)
            .assign(to: \.internalChangedValue, on: self)
            .store(in: &anyCancellables)
        toggleChangedPublisher
            .receive(on: RunLoop.main)
            .assign(to: \.internalChangedValue, on: self)
            .store(in: &anyCancellables)
        
    }
    private var nestedToggleChangedPublisher: AnyPublisher<Bool, Never> {
        // Not working on change of model
        $model
            .map({return $0.nestedIsToggled})
            .eraseToAnyPublisher()
    }
    

    private var toggleChangedPublisher: AnyPublisher<Bool, Never> {
        // Is working when toggled
        $isToggled
            .eraseToAnyPublisher()
    }
}

感谢您的支持!

【问题讨论】:

    标签: ios swift swiftui combine publisher


    【解决方案1】:

    也许我没有抓住重点,但你不能只使用计算属性吗?

    class ContentViewModel: ObservableObject {
        @Published var model = Model()
    
        var isToggled: Bool { model.nestedIsToggled }
    }
    

    【讨论】:

    • 在示例中这将是完全有效的,但我的意思是稍后使用发布者、映射等的组合组合。不过谢谢你的建议。
    • 好吧,我就是这么想的。我从未使用过您正在使用的组合地图,所以我不知道如何为您提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多