Combineの使い方を学んでいるところです。私はRx(RxSwiftとRxJava)の経験があり、非常に似ていることに気づいています。
ただし、まったく異なる(そして一種の煩わしい)ことの1つは、Publisher
プロトコルがそのOutput
およびFailure
タイプにジェネリックを使用しないことです。代わりに、関連する型を使用します。
これは、多形のPublisher
型(_Publisher<Int, Error>
_など)を指定して、それらの型でPublisher
に準拠する型を単純に返すことができないことを意味します。代わりに_AnyPublisher<Int, Error>
_を使用する必要があり、eraseToAnyPublisher()
をすべての場所に含める必要があります。
これが唯一の選択肢であるなら、私はそれに耐えます。しかし、最近、Swiftの不透明型についても学びました。これを回避するためにそれらを使用できるかどうか疑問に思っています。
たとえば、_some Publisher
_を返し、Output
およびFailure
に特定の型を使用する関数を用意する方法はありますか?
これは不透明型の完璧なケースのようですが、不透明型を使用して関連する型を指定する方法があるかどうかはわかりません。
私はこのようなものを描いています:
_func createPublisher() -> some Publisher where Output = Int, Failure = Error {
return Just(1)
}
_
_some Publisher
_(迷惑な制限)で運がありませんでした。
1つのオプションは、AnyPublisher
を使用することです。
_func a() -> AnyPublisher<(a: Int, b: String), Never> {
return Just((a: 1, b: "two")).eraseToAnyPublisher()
}
func b() -> AnyPublisher<String, Never> {
return a().map(\.b).eraseToAnyPublisher()
}
a().sink(receiveValue: {
let x = $0 // (a: 1, b: "two)
})
b().sink(receiveValue: {
let x = $0 // "two"
})
_
あるいは、「Appleの方法」(標準ライブラリで使用する方法)は型エイリアス(またはラッパー構造体)のようです。
_enum PublisherUtils {
typealias A = Just<(a: Int, b: String)>
typealias B = Publishers.MapKeyPath<A, String>
// 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"
})
_
これがCombineフレームワークのPublishers
名前空間の目的です。
構造体は型エイリアスよりも不透明です。型エイリアスはCannot convert Utils.MyTypeAlias (aka 'TheLongUnderlyingTypeOf') to expected type ABC
のようなエラーメッセージを引き起こす可能性があるため、適切な不透明型に最も近いのは、構造体を使用することです。これは基本的にAnyPublisher
です。