【问题标题】:Swift Combine Conditional FlatMap ResultsSwift 合并条件 FlatMap 结果
【发布时间】:2021-03-06 14:53:56
【问题描述】:

在使用 Swift Combine 时,如何为 flatMap 提供不同的返回类型?我有我的第一个发布者,它发出一个值,然后我 flatMap 将其转换为一个新的发布者。但是,根据原始值,我可能需要一个不同的发布者来返回不同的类型。

我在下面添加了一个基本示例。

import Combine


class Testing{
    var subscriptions = Set<AnyCancellable>()
    
    
    func getTestScore()->AnyPublisher<Int, Never>{
        return Just(80).eraseToAnyPublisher()
    }
    
    func congratulate()->AnyPublisher<String, Never>{
        return Just("Good Job!").eraseToAnyPublisher()
    }
    
    func getGPA()->AnyPublisher<Double, Never>{
        return Just(2.2).eraseToAnyPublisher()
    }
    
    init() {
        getTestScore()
            .flatMap{ score in
                if score < 70{
                    return self.getGPA()
                } else{
                    return self.congratulate()
                }
            }
            .sink { _ in } receiveValue: { value in
                print(value)
            }.store(in: &subscriptions)
    }
}

let testing = Testing()

【问题讨论】:

  • getGPA 发出Double 值,而congratulate 发出String 值.. .sink 应该期待什么?这类似于想要从函数返回DoubleString。当然,您可以返回Any,但这只是一个糟糕的设计选择。您可以考虑使用具有关联值的枚举。
  • 你说得对,any 不是一个好的解决方案。具有关联值的枚举可能也不是最佳选择。
  • 在您的问题中,您发布了一个“玩具”示例......也许真正的问题在该示例中并不明显?
  • 几乎一样。真正的问题是我有一个配置文件视图,我在其中加载用户。然后我必须检查用户是否是当前登录的用户。如果是,那么我必须进行两次网络调用(a 和 b)。如果它不是登录用户,那么我只需要进行网络调用。
  • 这听起来完全不同。我建议您发布一个与您实际需要更相关的不同问题。

标签: swift conditional-statements combine flatmap


【解决方案1】:

正如 New Dev 所说,返回条件数据类型是不可能的 - 除非您不想将类型擦除为 Any

我的建议是创建一个专门的发布者,如果分数超过(或低于)某个限制,它就会发出。现在使用您的新发布者创建两个单独的、类型安全的管道。我知道您要求只使用一个管道。但是,我认为这种方法会给您带来更多好处。

请在下面找到我的工作示例:

import Combine

class Testing{
    var subscriptions = Set<AnyCancellable>()
    
    func getTestScore()->AnyPublisher<Int, Never> {
        return Just(80).eraseToAnyPublisher()
    }
    
    func congratulate()->AnyPublisher<String, Never> {
        return Just("Good Job!").eraseToAnyPublisher()
    }
    
    func getGPA()->AnyPublisher<Double, Never> {
        return Just(2.2).eraseToAnyPublisher()
    }
    
    init() {
        let scoreExceedsLimit: AnyPublisher<Bool, Never> = getTestScore()
            .map { $0 >= 70 }
            .eraseToAnyPublisher()
        
        scoreExceedsLimit
            .filter { $0 == true }
            .flatMap { _ in self.congratulate() }
            .sink(receiveValue: { value in
                print("first pipeline: \(value)")
            })
            .store(in: &subscriptions)
        
        scoreExceedsLimit
            .filter { $0 == false }
            .flatMap { _ in self.getGPA() }
            .sink(receiveValue: { value in
                print("second pipeline: \(value)")
            })
            .store(in: &subscriptions)
    }
}

let testing = Testing()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    相关资源
    最近更新 更多