⏲️
【Swift】Combineで定期的なタイマー処理を行う方法
はじめに
この記事の主張
-
Timer.publish
を使って定期的なタイマー処理を実現する - Combineのパイプラインを使って指定されたタイマー間隔で処理を実行
やりたいこと
上部の文言(紫色で囲った枠内の文章)を30秒ごとに違う文字に変更したい。
文章一覧
let data: [String] = [
"お疲れ様です。",
"いつも頑張っていますね。",
"ほっと一息ついてみましょう。",
"無理しないでくださいね。",
"今日もご苦労様です。",
"頑張った自分にご褒美してくださいね。",
"たまにはゆっくりしてみてください。",
"心を落ち着かせましょう。",
"深呼吸してみましょう。",
"今日の自分を褒めてみましょう。",
"明日もいい日になりますよ。"
]
本題
完成形
import Foundation
import Combine
class EncouragingWordList: ObservableObject {
let data: [String] = [
"お疲れ様です。",
"いつも頑張っていますね。",
"ほっと一息ついてみましょう。",
"無理しないでくださいね。",
"今日もご苦労様です。",
"頑張った自分にご褒美してくださいね。",
"たまにはゆっくりしてみてください。",
"心を落ち着かせましょう。",
"深呼吸してみましょう。",
"今日の自分を褒めてみましょう。",
"明日もいい日になりますよ。"
]
@Published var currentWord: String = ""
private var cancellablePipeline: AnyCancellable?
init() {
self.currentWord = data[0]
cancellablePipeline = Timer
.publish(every: 30.0, on: .main, in: .common)
.autoconnect()
.sink { [unowned self] _ in
if let currentData = data.randomElement() {
self.currentWord = currentData
}
}
}
}
Timer.publish
を使って定期的なタイマー処理を実現する
30秒ごとに値(日付)を返すにはTimer.publish
を使用します。
Timer
.publish(every: 30.0, on: .main, in: .common)
.autoconnect()
.publish(every:on:in:)
は指定の間隔で現在の日付を出力するPublisherを返します。
autoconnect()
を使用すると、Subscriberが与えられたときにPublisherからSubscriberへのパイプラインを自動的に接続します。
これで、30秒ごとに、上流からパイプラインを通ってデータが流れてきます。
あとは受け口での処理を作るだけです。
Combineのパイプラインを使って指定されたタイマー間隔で処理を実行
次にパイプラインの受け口の処理を作ります。
いつでも受け口側でキャンセル可能なSubscriberであるsink
を使います。
(キャンセル可能とは、水道の蛇口のように、いつでも止めたり開けたりできる仕組みです。)
Timer
.publish(every: 30.0, on: .main, in: .common)
.autoconnect()
.sink { [unowned self] _ in
if let currentData = data.randomElement() {
self.currentWord = currentData
}
}
.sink
では以下を実行してます。
- 配列
data
からランダムに要素を取得して、定数currentData
に格納 -
currentData
をcurrentWord
に格納してViewに反映
まとめ
実現したいこと
指定のタイマー間隔ごとに定期的に処理を実行する
実現方法
cancellablePipeline = Timer
.publish(every: ここにタイマー間隔を指定, on: .main, in: .common)
.autoconnect()
.sink { [unowned self] _ in
// ここに処理を記述
}
Discussion