Observable 객체와 Environment 객체 튜토리얼

1 분 소요

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())
    }
}

카테고리:

업데이트: