Observable 객체와 Environment 객체 튜토리얼
ObservableDemo 프로젝트에 대하여
Observable 객체: 동적 데이터(시간이 지남에 따라 반복적으로 변하는 데이터 값) 래핑에 효과적
-> Timer 객체 사용
Observable 객체 추가하기
ObservableObject 프로토콜을 구현하는 데이터 클래스 추가
<TimerData 클래스>
import Foundation // Timer 객체
import Combine // Observable 객체
class TimerData : ObservableObject {
@Published var timeCount = 0
var timer : Timer?
init() {
timer = Timer.scheduledTimer(timeInterval: 1.0,
target: self,
selector: #selector(timerDidFire),
userInfo: nil,
repeats: true)
}
@objc func timerDidFire() {
timeCount += 1
}
func resetCount() {
timeCount = 0
}
}
매 초마다 timerDidFire() 함수 호출
timeCount 프로퍼티: 게시된 프로퍼티(@Published)
- 프로젝트 내에 있는 뷰에서 관찰가능
ContentView 레이아웃 설계하기
import SwiftUI
struct ContentView: View {
@ObservedObject var timerData: TimerData = TimerData() // 구독(subscribe)
var body: some View {
NavigationView {
VStack {
Text("Timer count = \(timerData.timeCount)")
.font(.largeTitle)
.fontWeight(.bold)
.padding()
Button(action: resetCount) { // timerData.resetCount으로 대체가능?
Text("Reset Counter")
}
}
}
}
func resetCount() {
timerData.resetCount()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
두 번째 뷰 추가하기
import SwiftUI
struct SecondView: View {
@ObservedObject var timerData: TimerData // 초기화x
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()) // 참조체 전달
}
}
자신만의 TimerData 인스턴스 소유
동일한 인스턴스를 사용하려면 ObservedObject 객체를 SecondView에 전달해야함
내비게이션 추가하기
두 번째 뷰로 이동하는 내비게이션 링크 추가
NavigationLink(destination:
SecondView(timerData: timerData)) {
Text("Next Screen")
}
.padding()
첫 번째 뷰와 두 번째 뷰의 카운팅이 이어짐
두 개의 뷰 모두가 동일한 Observable 객체 인스턴스를 구독하고 있음
Environment 객체 사용하기
Environment 객체: 참조체를 전달하지 않아도 TimerData 객체에 접근 가능
<TimerData> - 수정x
<ContentView>
import SwiftUI
struct ContentView: View {
@EnvironmentObject var timerData: TimerData // 초기화x, Environment 객체로 변경
var body: some View {
NavigationView {
VStack {
Text("Timer count = \(timerData.timeCount)")
.font(.largeTitle)
.fontWeight(.bold)
.padding()
Button(action: resetCount) {
Text("Reset Counter")
}
NavigationLink(destination: SecondView()) { // 참조체 전달x
Text("Next Screen")
}
.padding()
}
}
}
func resetCount() {
timerData.resetCount()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(TimerData()) // 타이머의 인스턴스 추가
}
}
<SecondView>
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())
}
}