Is there a way to avoid using AnyPublisher/eraseToAnyPublisher all over the place?

后端 未结 3 1598
太阳男子
太阳男子 2021-02-08 11:46

I\'m just learning how to use Combine. I have experience with Rx (RxSwift and RxJava) and I\'m noticing that it\'s quite similar.

However, one thing that is quite differ

3条回答
  •  梦毁少年i
    2021-02-08 12:07

    I had no luck with some Publisher (annoying restriction).

    One option is to use AnyPublisher:

    func a() -> AnyPublisher<(a: Int, b: String), Never> {
        return Just((a: 1, b: "two")).eraseToAnyPublisher()
    }
    
    func b() -> AnyPublisher {
        return a().map(\.b).eraseToAnyPublisher()
    }
    
    a().sink(receiveValue: {
        let x = $0 // (a: 1, b: "two)
    })
    
    b().sink(receiveValue: {
        let x = $0 // "two"
    })
    

    Alternatively, the "Apple way" (what they use in the standard library) seems to be type aliases (or wrapper structs):

    enum PublisherUtils {
        typealias A = Just<(a: Int, b: String)>
        typealias B = Publishers.MapKeyPath
        // or implement a simple wrapper struct like what Combine does
    }
    
    func a() -> PublisherUtils.A {
        return Just((a: 1, b: "two"))
    }
    
    func b() -> PublisherUtils.B {
        return a().map(\.b)
    }
    
    a().sink(receiveValue: {
        let x = $0 // (a: 1, b: "two)
    })
    
    b().sink(receiveValue: {
        let x = $0 // "two"
    })
    

    This is the purpose of the Publishers namespace in the Combine framework.

    Structs are more opaque than type aliases. Type aliases can result in error messages like Cannot convert Utils.MyTypeAlias (aka 'TheLongUnderlyingTypeOf') to expected type ABC, so the closest you can get to proper opaque types is probably to use a struct, which is essentially what the AnyPublisher is.

提交回复
热议问题