Introduction to Combine | Supporting 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.

If you want other samples, see following articles.

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)
        }
    }
}

Author Profile

Akira HayashiA professional developer specializing in macOS Apps, iOS Apps, SDKs and middleware development.
Representative of RK Kaihatsu. I am a professional developer specializing in macOS Apps, iOS Apps, SDKs and middleware development. I often use ObjC, Swift and C++. Based on development experience, I provide e-learning contents, technical books and technical guidance. I am also a technical seminar instructor, in-house training instructor, and administrative / local goverment staff training instructor.
Get the Latest News !

App DeveloperLatest 8 Posts

>Programming Tips From Software Engineer

Programming Tips From Software Engineer

Technical News, Documents and Tips.

CTR IMG