0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SwiftUIAdvent Calendar 2023

Day 8

Swift 27 Observable

Last updated at Posted at 2023-12-08

22章'SwiftUI 状態プロパティ、Observable, State, Environment客体'でObservable客体とEnvironment客体について紹介したって、SwiftUIアプリを開発するときもデータ主導方法で実装する方法について説明しました。

今度章には前で学びだった内容を持ってObservable客体とEnvironment客体を利用した簡単な例題プロジェクトを生成するだろう。

二十七・壱 ObservableDemoプロジェクトについて

Observable客体は時間が時間が経つにつれて反復的に変わるデータ値な動的データをラッピングするに使用される時に特に強いです。そのタープのデータをシミュレーターするためにFoundationフレームウーアクのTimerオブジェクトを使用者して毎秒カウンターがアプデイトする様に構成してObservableデータオブジェクトを生成するだろ。このカウンターはアプリプロジェクト内のビュー {が見られるようにpublishされるだろう。

まずは、データはObservableオブジェクトで扱われるだろうし他のビューで伝達するだろう。今度の章の後半部にはこのデータをEnvironmentオブジェクトで転換して他のビューを伝達しなくてもほかのビューが接近される様にだろう。

二十七・弍 プロジェクト生成する

ObservableDemoと言う名前の新しいMultiplatform Appを生成しょう
まず、ObservableObjectプロトコルを実装するデータクラスを追加する事です。
その後、TimerDataで新しいSwift Fileを作った後次のコードを作成してTimerDataクラスを実装します。

import SwiftUI
import Combine

class TimerData: ObservableObject {
    @Published var timeCount: Int = 0
    var timer : Timer?

    init() {
        // Set up a timer to update the counter every second
        timer = Timer.scheduledTimer(timeInterval: 1.0,
                                     target: self,
                                     selector: #selector(timerDidFire),
                                     userInfo: nil,
                                     repeats: true )
    }
    @objc func timerDidFire(){
        timeCount += 1
    }
    func resetCount() {
        timeCount = 0
    }
}

このクラスはObservableObjectプロトコルを実装するもので宣言されったし、Timerインスタンスは毎秒timerDidFire()と言う名前の関数を呼び出す様に構成するinit{}も含まれました。timerDidFire()関数はtimeCount変数で割り当てた値を増加させる。timeCount変数は@Publishedプロパティラッファーを使って宣言されてプロジェクト内であるビューで観察される事ができます。また、このクラスはカウンターを0でリセットするresetCount()と言うメソッドも持っています。

弍・一 ContentViewレイアウトvhz設計する

アプリの使用者インタフェイスは二つの画面で構成される様です。一番ビューはContentView.swift ファイルによって表示されます。そのファイルを選択して次の様に修正しましょう

truct ContentView: View {
    @StateObject var timerData : TimerData = TimerData()
    
    var body: some View {
        
        NavigationView{
            VStack {
                Text("Timer count = \(timerData.timeCount)")
                    .font(.largeTitle)
                    .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
                    .padding()
                
                Button(action: resetCount){
                    Text("Reset Counter")
                }
            }
        }
    }
    func resetCount(){
        timerData.resetCount()
    }
}

#Preview {
    ContentView()
}

その様に修正したらlive previewを見るとカウンターが増加します。
次には、Reset Counterを押してカウンターが0からまたカウンティングするがを確認します。次には、同一なObservableオブジェクトを接近する2番目のビューを追加する事です。

弍・二 2番目のビューを追加する

新しい.Swift ファイルを生成してSecondViewと言うファイルを生成しましょう。
その後、次の様に作成してみましょう

struct SecondView: View {
    @StateObject var timerData : TimerData
    
    var body: some View {
        
            VStack {
                Text("Second View")
                    .font(.largeTitle)
                Text("Timer count = \(timerData.timeCount)")
                    .font(.headline)
            }
            .padding()
    }
}


struct SecondView_Previews: PreviewProvider {
    static var previews: some View {
        SecondView(timerData: TimerData())
    }
}

ライブプリビュウを利用してレイアウトvhzをテストすると、ターマがカウンティングを始めるだろう。

ここでこのビューはSecondView_Previews宣言部で構成された自身だけのTimerDataインスタンスを持ちます。ContentViewとSecondView全て同一なTimerDataインスタンスを使用すると使用者が2番目の画面で移動する時一番目ビューにあるObservedObjectオブジェクトをSecodneViewで伝達するべきです。

二十七・参 Navigation 追加する

2番目ビューで移動する様にContentViewでNavigation linkが追加されるべきです。次のリンクを追加します。

  var body: some View {
        
        NavigationView{
            VStack {
                Text("Timer count = \(timerData.timeCount)")
                    .font(.largeTitle)
                    .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
                    .padding()
                
                Button(action: resetCount){
                    Text("Reset Counter")
                    
+                    NavigationLink(destination: SecondView(timerData: +timerData)){
+                        Text("Next Screen")
+                    }
+                    .padding()
                }
            }
        }
    }

また、Previewを使ってContenViewのカウンターが増加するかを確認します。現在のカウンター値を覚えて、Next Screenリンクを押して2番目のビューが表示させる様にして覚えたカウンター数字から続けてカウンティングがつながっているかを確認します。これは二つのビュー全てが同一なObservableオブジェクトインスタンスを購読していることを確認してあげます。

二十七・肆 Environmentオブジェクト使う

今度のチュとリアルでする最後の作業はObservableオブジェクトをEnvironmentオブジェクトで変換することです。こうすると二つのビューが同一なTimerDataオブジェクトに対する参照を伝達しなくても接近できるよになるます。

今度の修正作業はTimeData.swiftクラス宣言部を修正する必要がなくて二つのSwiftUIビューファイルで少し修正ずればできます。ContentView.swiftファイルから始めよう。timerDataがも以上SecondViewで伝達されない様にNavigation Linkのdestinationを修正します。また、environmentObject()修正者を追加してtimerDataインスタンスをビュー階層で環境で入れます。

struct ContentView: View {
    @StateObject var timerData : TimerData = TimerData()
    
    var body: some View {
        
        NavigationView{
            VStack {
                Text("Timer count = \(timerData.timeCount)")
                    .font(.largeTitle)
                    .fontWeight(/*@START_MENU_TOKEN@*/.bold/*@END_MENU_TOKEN@*/)
                    .padding()
                
                Button(action: resetCount){
                    Text("Reset Counter")
                    
+                    NavigationLink(destination: SecondView()){
                        Text("Next Screen")
                    }
                    .padding()
                }
            }
+            .environmentObject(timerData)
        }
    }
    func resetCount(){
        timerData.resetCount()
    }
}

次て、SecondView.siwftファイルを修正します。

import SwiftUI

struct SecondView: View {
+    @EnvironmentObject var timerData : TimerData
    
    var body: some View {
        
            VStack {
                Text("Second View")
                    .font(.largeTitle)
                Text("Timer count = \(timerData.timeCount)")
                    .font(.headline)
            }
            .padding()
    }
}


struct SecondView_Previews: PreviewProvider {
    static var previews: some View {
+        SecondView().environmentObject(TimerData())
    }
}

live previewま実際デバイスとかシミュレーターを利用して二つ画面全部同一なカウンターデータで接近するかどうかをプロジェクトをテストしましょう。

要約

今度の章で使用者インタフェイ内のビューと動的データをバインディングするためObservableオブジェクトとEnvironmentオブジェクトをどう使用するかを見せるチュートリアルを真似したし、また、Observalbeオブジェクトを実装してプロパティを投稿して、ObservableオブジェクトとEnvironmentオブジェクトを購読する方法も調べてみた.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?