Introduction to Combine | How to support Combine in a custom class

Combine is a framework to implement asynchronous operations. It is created by Apple, it is also used in Swift Data Binding. It is an important framework.

If you new to Combine, see next article.

現役のプログラマーが書くプログラミング情報

Combineはアップル純正の非同期処理を実装するためのフレームワークです。SwiftUIのバインディングなどでも使われ…

If you want other samples, see following articles.

現役のプログラマーが書くプログラミング情報

TimerもCombineに対応しています。Timerで定期的に実行される処理をCombineを使って設定出来るようにな…

This article explains how to support Combine in a custom class.

スポンサーリンク

Adopt to ObservableObject protocol.

To make a class to support Combine, adopt to ObservableObject protocol.

To notify a changes of properties with Combine, mark the property with @Published attribute.

class PlayerStatus : ObservableObject {
    @Published var name: String = ""
    @Published var hitPoint: Int = 100
}

@Published

The property which is marked with @Published attribute, can make the Publisher.

Use $ operator to make the Publisher.

let status = PlayerStatus()
let hitPointPublisher = status.$hitPoint

Receive changes of properties of a custom class

Use sink() to receive changes.

let cancellable = status.$hitPoint.sink { (value) in 
    // Block when a property is changed.
}

The value of the property is not changed at the block is executing, so the value of the property is an old value yet. You should use a block argument “value”.

Sample Application

I made a sample application. “Hit” button decrement HP and “Heal” button recover it. I think this code will make you understand an effect of the ObservableObject.

import UIKit
import Combine

class PlayerStatus: ObservableObject {
    @Published var name:String = ""
    @Published var hitPoint: Int = 100
}

class ViewController: UIViewController {
    @IBOutlet var hitPointLabel: UILabel!
    
    var playerStatus: PlayerStatus = PlayerStatus()
    var hitPointCancellable: AnyCancellable? = nil

    private func refresh(hitPoint: Int) {
        self.hitPointLabel.text = "(hitPoint)"
    }
    
    @IBAction func hit(_ sender: Any?) {
        if self.playerStatus.hitPoint > 0 {
            self.playerStatus.hitPoint -= 10
        }
    }
    
    @IBAction func heal(_ sender: Any?) {
        self.playerStatus.hitPoint = 100
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        refresh(hitPoint: self.playerStatus.hitPoint)
        
        hitPointCancellable = self.playerStatus.$hitPoint.sink { (value) in
            self.refresh(hitPoint: value)
        }
    }
}

スポンサーリンク
最新情報をチェックしよう!
>現役のプログラマーが書くプログラミング情報

現役のプログラマーが書くプログラミング情報

日々の開発の中での学びや分かったこと、調べたことなどを書いていくブログです。

CTR IMG