如何创建可以具有任何类型输出的 PassthroughSubject?

How do I create a PassthroughSubject that can have an output of any type?

我想创建一个可以发送任何类型输出的 PassthroughSubject 对象。在代码中我目前有这样的东西:

let cmd1Subj = PassthroughSubject<String, Never>()
let cmd2Subj = PassthroughSubject<String, Never>()
var desiredCmd: PassthroughSubject<String, Never>?
let executeDesiredCmdSubj = PassthroughSubject<String, Never>()
var arg: String?

func executeDesiredCmd(cmdArg: String) -> AnyPublisher<String, Never> {
    guard (desiredCmd != nil) else {
        return Just("Nothing to execute\n").eraseToAnyPublisher()
    }
    desiredCmd?.send(cmdArg)
    return Just("Executed: \(String(describing: desiredCmd)) with argument: \(cmdArg)").eraseToAnyPublisher()
}

let cancellable = executeDesiredCmdSubj
    .flatMap(executeDesiredCmd)
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: {
        print([=10=])
    })

desiredCmd = cmd1Subj
arg = "This is the argument for command 1"
desiredCmd?.send(arg!)
desiredCmd = cmd2Subj
arg = "This is the argument for command 2"
desiredCmd?.send(arg!)

如何更改 desiredCmdexecuteDesiredCmdSubj 以便它们可以发送运行时确定的任何类型的输出?我想做这样的事情:

let cmd1Subj = PassthroughSubject<Int, Never>()
let cmd2Subj = PassthroughSubject<String, Never>()
var desiredCmd: PassthroughSubject<Some_Generic_Type, Never>?
let executeDesiredCmdSubj = PassthroughSubject<Some_Generic_Type, Never>()
var arg: Some_Generic_Type?

func executeDesiredCmd(cmdArg: Some_Generic_Type) -> AnyPublisher<String, Never> {
    guard (desiredCmd != nil) else {
        return Just("Nothing to execute\n").eraseToAnyPublisher()
    }
    desiredCmd?.send(cmdArg)
    return Just("Executed: \(String(describing: desiredCmd)) with argument: \(cmdArg)").eraseToAnyPublisher()
}

let cancellable = executeDesiredCmdSubj
    .flatMap(executeDesiredCmd)
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: {
        print([=11=])
    })

desiredCmd = cmd1Subj
arg = 12345
desiredCmd?.send(arg!)
desiredCmd = cmd2Subj
arg = "This is the argument for command 2"
desiredCmd?.send(arg!)

其中 Some_Generic_Type 是一个占位符,可用于表示我试图通过我的 PassthroughSubject 传递的任何类型。我尝试使用“Any”作为占位符,但它会产生一些编译错误:

我能够通过创建一个结构来做到这一点,该结构定义了几个具有关联值的枚举:

struct VersatilePassthroughSubject {
    enum SubjectOutputType {
        case subjAsStringOutput(PassthroughSubject<String, Never>)
        case subjAsIntOutput(PassthroughSubject<Int, Never>)
    }
    
    enum Arg {
        case argAsString(String)
        case argAsInt(Int)
    }
    
    var subj: SubjectOutputType? = nil
    var arg: Arg? = nil
}

let cmd1Subj = PassthroughSubject<Int, Never>()
let cmd2Subj = PassthroughSubject<String, Never>()
var desiredCmd: VersatilePassthroughSubject = VersatilePassthroughSubject()
let executeDesiredCmdSubj = PassthroughSubject<Void, Never>()

func executeDesiredCmd() -> AnyPublisher<String, Never> {
    guard (desiredCmd.subj != nil) else {
        return Just("Nothing to execute\n").eraseToAnyPublisher()
    }
    if case .subjAsIntOutput(let subj) = desiredCmd.subj {
        if case .argAsInt(let arg) = desiredCmd.arg {
            subj.send(arg)
            return Just("Executed: \(String(describing: desiredCmd)) with argument: \(arg)").eraseToAnyPublisher()
        }
    }
    else if case .subjAsStringOutput(let subj) = desiredCmd.subj {
        if case .argAsString(let arg) = desiredCmd.arg {
            subj.send(arg)
            return Just("Executed: \(String(describing: desiredCmd)) with argument: \(arg)").eraseToAnyPublisher()
        }
    }
    return Just("Nothing to execute\n").eraseToAnyPublisher()
}

let cancellable = executeDesiredCmdSubj
    .flatMap(executeDesiredCmd)
    .receive(on: DispatchQueue.main)
    .sink(receiveValue: {
        print([=10=])
    })

desiredCmd.subj = .subjAsIntOutput(cmd1Subj)
desiredCmd.arg = .argAsInt(12345)
executeDesiredCmdSubj.send()
desiredCmd.subj = .subjAsStringOutput(cmd2Subj)
desiredCmd.arg = .argAsString("This is the argument for command 2")
executeDesiredCmdSubj.send()