Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【Combine】Justの特徴と使い所

 

はじめに

Justの具体的な挙動や使い所について、Appleのドキュメントを読み返したり、サンプルで動きを確かめてみました。

 

開発環境

 

本題

Justの特徴

"A publisher that emits an output to each subscriber just once, and then finishes."

"In contrast with Result.Publisher, a Just publisher can’t fail with an error. And unlike Optional.Publisher, a Just publisher always produces a value."

※引用:https://developer.apple.com/documentation/combine/just

 

上記によると、Justは以下の特徴があります。

  • サブスクライバーに一度だけ値を送信(発行)し終了するパブリッシャー
  • 失敗することができない
  • 必ず値を送信(発行)する

 

具体的にはどのように値を送信しているのかprint()で確認してみます。

private let sampleString = "Hello World!"

private var cancellables: Set<AnyCancellable> = []

init() {
    // Justを使わない場合
    sampleString.publisher
        .compactMap( { String($0) } )
        .sink(receiveValue: {
            print($0)
        })
        .store(in: &cancellables)
    
    // Justを使う場合
    Just(sampleString)
        .compactMap( { String($0) } )
        .sink(receiveValue: {
            print($0)
        })
        .store(in: &cancellables)
}

f:id:hfoasi8fje3:20210806221158p:plain

Justを使わない場合は値を一つずつ送信しているのに対し、Justは値をそのまま送信し終了しています。

 

Justは呼ばれた時点(今回はinit)で一度だけ値を送信するため、以下のように実装しても、TextFieldで入力した値を監視することはできません。

ContentView.swift

import SwiftUI
import Combine

struct ContentView: View {
    @ObservedObject private var viewModel: ContentViewModel
    
    init(viewModel: ContentViewModel) {
        self.viewModel = viewModel
    }
    
    var body: some View {            
            TextField("文字を入力", text: $viewModel.textA)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                .frame(width: 300)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(viewModel: ContentViewModel())
    }
}

 

ContentViewModel.swift

import Foundation
import Combine

final class ContentViewModel: ObservableObject {
    @Published var textA = ""
    
    private var cancellables: Set<AnyCancellable> = []
    
    init() {
        // 呼ばれた時点でのtextAの値(今回は空文字)を一度だけ送信して終了するため、
        // この実装ではTextFieldの値を監視することはできない
        Just(textA)
            .sink(receiveValue: {
                print($0)
            })
            .store(in: &cancellables)
    }
}

 

Justの使い所

 "A Just publisher is also useful when replacing a value with Publishers.Catch."

 ※引用:https://developer.apple.com/documentation/combine/just 

 

Catchを使って値を置き換える時に便利と記載があります。以下Appleのドキュメントで例を見ることができます。

※参考:https://developer.apple.com/documentation/combine/fail/catch(_:)

 

また、以下ではtryMapの処理がエラーとなった時に、tryCatch(_:)内のJustによって定義した値を送信して処理を完了するサンプルがあります。

※参考:https://developer.apple.com/documentation/combine/fail/trycatch(_:)

 

エラー時の値の置き換え時に便利というところまでは理解できました。

 

おわりに

Combineの基本についてドキュメントを探していると、「Publishersはこういうもので、Operatorsはこういうもの、Subscribersはこういうものです。次にJustですが・・・」と、Combineの概要を説明した後にJustの説明が始まることが多いのですが、なぜこの順序で突然「便利なPublishersの一つ」が紹介されるのか意図がわからず一人で勝手に混乱しました笑 「そんなにJustって重要なの?何か重要な役割があるの?」と感じてしまったのですが、自分だけか・・・笑

 

参考