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.

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)
        }
    }
}
Sponsored Links
Get the Latest News !