获取可以更新值的 @Published 的引用

Get reference for an @Published that can update the value

我正在尝试动态更新对 @Published var 的引用,但我不确定该怎么做。仅返回值只是一个 bool 值,并且会丢失它对发布者的引用并且不起作用。我尝试返回发布者本身 ($self.isBig) 但我似乎无法弄清楚一旦拥有发布者而不是 @Published 属性.

如何更新值

我基本上只是尝试将 @Published 视为参考并更新 class 上的参考,而不是复制发布者的值。

这是一个人为的例子,只是为了说明问题,我想做的是:

import UIKit
import Combine

class MyClass {
    
    struct MyData {
        enum MyDataType {
            case big
            case yellow
            case bird
        }
        var type: MyDataType
        var isEnabled: Bool
    }
    
    private var cancellables = Set<AnyCancellable>()
    
    @Published var isBig: Bool = false
    @Published var isYellow: Bool = false
    @Published var isBird: Bool = false
    
    var mySwitch = UISwitch()
    
    init() {
        // Add mySwitch and setupSubscribers...
    }

    func updatePublishers(from data: MyData) {
        let publisherForData = specificPublisherForData(data)
        // I want to access the underlying value for the @Published and set it here
//        publisherForData = data.isEnabled
    }

    func specificPublisherForData(_ data: MyData) -> Published<Bool>.Publisher {
        switch data.type {
        case .big: return self.$isBig
        case .yellow: return self.$isYellow
        case .bird: return self.$isBird
        }
     }
    
    func setupSubscribers() {
        $isBig.sink { [weak self] isBig in
            guard let self = self else { return }
            
            self.mySwitch.isOn = isBig
        }.store(in: &cancellables)
        
        // ... add subscribers for the other ones
    }
}

您似乎在尝试为 updatePublishers 中的 Publisher 分配一个 新值,但实际上并非如此 @Publisher 的工作——他们只是在传播价值观。

相反,您可能需要使用关键路径:

class MyClass {
    
    struct MyData {
        enum MyDataType {
            case big
            case yellow
            case bird
        }
        var type: MyDataType
        var isEnabled: Bool
    }
    
    private var cancellables = Set<AnyCancellable>()
    
    @Published var isBig: Bool = false
    @Published var isYellow: Bool = false
    @Published var isBird: Bool = false
    
    var mySwitch = UISwitch()
    
    init() {
        // Add mySwitch and setupSubscribers...
    }

    func updatePublishers(from data: MyData) {
        let keypath = specificKeypathForData(data)
        self[keyPath: keypath] = data.isEnabled
    }

    func specificKeypathForData(_ data: MyData) -> ReferenceWritableKeyPath<MyClass,Bool> {
        switch data.type {
        case .big: return \.isBig
        case .yellow: return \.isYellow
        case .bird: return \.isBird
        }
     }
    
    func setupSubscribers() {
        $isBig.sink { [weak self] isBig in
            guard let self = self else { return }
            
            self.mySwitch.isOn = isBig
        }.store(in: &cancellables)
        
        // ... add subscribers for the other ones
    }
}

在操场上:

var myClass = MyClass()
myClass.setupSubscribers()
var data = MyClass.MyData(type: .big, isEnabled: true)
myClass.updatePublishers(from: data)
print(myClass.isBig)

产量:

true