0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Combine(Swift)に関しての特に参考になった知見

Last updated at Posted at 2022-04-15

スレッドについて

.receive(on: DispatchQueue.main)を用いるとメインスレッドで受けれるので良さそうである。
.receive(on: RunLoop.main)は、スクロール中に止まるらしい(Timerがスクロール中に止まるのと同じく)

UIControlをCombineで購読したい

デフォルトで用意されているものはない。

CombineCocoaを利用すればできる模様。
UIKitでもCombineしたい!を叶えるCombineCocoaを試してみる
もしUIKitでUIを作りCombineで非同期処理を行うなら絶対にCombineCocoaの導入を検討するべきではないだろうか
CombineCommunity/CombineCocoa

自分でPublisher, Subscriptionを作っても良い。

zafarivaev/UIControl+Combine.swift
Observe UIButton Events Using Combine in Swift 5
Subscription
Publisher

RxSwiftとCombineの対応

非常に便利なチートシートがあった。
RxSwift to Combine Cheatsheet

Timerについて

上記チートシートにも少し書いてあるが、Combineでは以下のように実装する。

  • 以下、引用
Timer.swift
    func startCounting() {
        isTimerRunning = true
        cancellable = Timer.publish(every: 1.0, on: .main, in: .common)
            .autoconnect()
            .sink { _ in
                self.count += 1
            }
    }

上記を軽く解説すると、Timer.publishConnectablePublisher(connectメソッドを呼ばれて初めてイベントを発生させる)というものだが、特にそのような機能を利用しないので、.autoconnect()を呼んで普通のpublisherのような振る舞いに戻しているようである。

setFailureType()について

  • 以下、引用
Int+extension.swift
extension Int {
    enum NumberConvertError: Error {
        case convert
    }

    func toAnyPublisher(string: String) -> AnyPublisher<Int, Error> {
        guard let number = Int(string) else {
            return Fail(error: NumberConvertError.convert)
            .eraseToAnyPublisher()
        }
        return Just(number)
            .setFailureType(to: Error.self)
            .eraseToAnyPublisher()
    }
}

PublisherのFailureがNeverの場合のみに使用でき
指定したError Protocolに適合した型を出力するPublisherに変換します。
上記の例ですとJustからJustに変換しています

逆にErrorを含むパブリッシャーをErrorを返さないパブリッシャーに変えたい時は、mapError(_:)が使える。

自分独自のオペレータを作りたい

extensionを利用して作ることができる。以下は一例。

Publisher+CustomOperators.swift
import Foundation
import Combine

extension Publisher {
    
    func throttleForTap()  -> AnyPublisher<Output, Failure> {
        return self.throttle(
                for: RunLoop.SchedulerTimeType.Stride(Const.tapThrottleDuration),
                scheduler: RunLoop.main,
                latest: false
            )
        .eraseToAnyPublisher()
    }
}

参考: Custom Operators in Swift Combine

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?