見出し画像

SwiftUIで行こう!Timer!

参考にしたサイトと公式のチュートリアルです。

UIKit で使ってきたTimerですが、SwiftUIで使う場合少し使い方が違うようなので少し調べてみました。

Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector (TimerViewController.refreshCells), userInfo: nil, repeats: true)

まずUIKitでは上記使ってました。SwiftUIでは、このままでは使いません。

今回はボタンを押したらカウントアップするものを考えていきます。

import SwiftUI

struct ContentView : View {

   var body: some View {
       VStack {
           Button("Start Timer") { // action code }
           Text( // count up code))
       }
   }
}

ボタンと数字を縦に並べて表示するコードです。これが基本になります。

次にカウントアップするクラスを書いていきます。

ここで大事なプロトコルの話。使い所も参考になります。

今回使うべきプロトコルは、いろいろ開発の段階で使用が変わっていて最終的には、

ObservableObject

を使えば良いようですね。ObservableObjectを使うときは

import Combine

変化する変数には

@Published

を前置詞としてつけます。これセットで使います。

コードはswiftファイルを新規で作成しています。

import SwiftUI
import Combine

class TimerHolder : ObservableObject {
    @Published var timer : Timer!
    @Published var count = 0 

   func start() {
       self.timer?.invalidate()
       self.count = 0
       self.timer = Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) {
           _ in
           self.count += 1
       }
   }
}

としています。Timer()を使ってカウントアップします。

そして"ContentView"です。メインのコードを書いていきます。

struct ContentView : View {
   @EnvironmentObject var timerHolder : TimerHolder
   var body: some View {
       VStack {
           Button("Start Timer") { self.timerHolder.start() }
           Text(String(self.timerHolder.count))
       }
   }
}

TimerHolderを継承したtimerHolder変数を作ります。ここで大事なのが

@EnvironmentObject

です。Viewの階層をまたがって値の更新通知を受け取ることができます。@Stateとの違いを理解しといた方が良いですね。そして、Bottunに命令を書きます。

{ self.timerHolder.start() }

です。Textにも

(self.timerHolder.count)

カウントの数を表示させます。

トータルのコードです。

 VStack {
           Button("Start Timer") { self.timerHolder.start() }
           Text(String(self.timerHolder.count))
       }

で縦にボタンと文字列を並べます。

最後に忘れずにつけないといけないのが

.environmentObject(TimerHolder()) )

を付け加えることです。SceneDelegate.swiftにつけます。起動時に起動ファイルを指定して必要なことを通知します。

window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(TimerHolder()) )

こうすることで連携がうまくいきます。実行画面です。

画像1

これでボタンを押すことでタイマーがスタートしてその数字が表示されます。

この記事が気に入ったらサポートをしてみませんか?