[SwiftUI]SwiftUIのデータクラスの更新監視@ObservedObject
SwiftUIにはデータクラスの更新を監視する仕組みとしてObservedObjectというものがある。今回はこれについて記載する。
1. @Stateとの違いは?
@StateはViewのプロパティが更新された際にViewの再描画を行うものだが、@ObservedObject はデータクラス(後述するObservableObjectプロトコルに準拠)のプロパティ(後述する@Publishedが付与されたプロパティ)の更新を監視し、更新されたらViewを再描画するという仕組み。
2. サンプルコード
struct ContentView: View {
@ObservedObject var quizModel = QuizModel()
var body: some View {
VStack {
Text("第\(quizModel.quizNumber)問")
.font(.largeTitle)
.padding(.bottom, 30)
Text(quizModel.currentQuiz.text)
.font(.title)
HStack {
Button {
quizModel.answerQuiz(playAnswer: true)
} label: {
CircleView()
}
.padding()
Button {
quizModel.answerQuiz(playAnswer: false)
} label: {
CrossView()
}
.padding()
}
.padding()
Text("\(quizModel.collectCount)問正解")
.font(.body)
}
.padding()
.onAppear {
quizModel.fetchQuiz()
}
}
}
struct CircleView: View {
var body: some View {
Circle()
.stroke(Color.blue, lineWidth: 20)
.frame(width: 150, height: 150)
}
}
struct CrossView: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 150, y: 150))
path.move(to: CGPoint(x: 150, y: 0))
path.addLine(to: CGPoint(x: 0, y: 150))
}
.stroke(lineWidth: 20)
.fill(Color.red)
.frame(width: 150, height: 150)
}
}
class QuizModel: ObservableObject {
@Published var quizNumber = 0
@Published var currentQuiz = Quiz(text: "Dummy", answer: true)
@Published var collectCount = 0
let quizList = [
Quiz(text: "1+1=2?", answer: true),
Quiz(text: "3-5=2?", answer: false),
Quiz(text: "10/5=2?", answer: true),
]
func answerQuiz(playAnswer answer: Bool){
if currentQuiz.answer == answer {
collectCount += 1
}
fetchQuiz()
}
func fetchQuiz() {
quizNumber += 1
let nextQuiz = quizList.randomElement()
currentQuiz = nextQuiz!
}
}
struct Quiz {
let text: String
let answer: Bool
}
3. ソースコードの説明
簡単な算数の○×クイズです。
○または×をタップするとランダムで次の問題に進むといったもの。
クイズの進行管理はContentViewのプロパティquizModelが行っており、次のクイズなどをViewに通知したいため@ObservedObjectにしている。
このとき、上述したが@ObservedObjectのデータクラスはObservableObjectプロトコルに準拠したクラスであり、Viewに通知したいプロパティに@Publishedを付与する必要がある。
4. 終わりに
@Stateや@ObservedObjectのような仕組みのものをデータバインディングという。他にも@EnvironmentObjectといったものもあったりして、それぞれ用途が違うので場面に合わせて使い分ける。