ObservableDemo 프로젝트
- Observable 객체는 시간이 지남에 따라 반복적으로 변하는 데이터 (동적 데이터)를 래핑할 때 강력함
- 이런 데이터를 시뮬레이션하기 위해서는 Foundation 프레임워크의 Timer 객체를 사용하여 매 초마다 카운터가 업데이트 되도록 구성하여 Observable 데이터 객체 생성할 것임
- 이 카운터는 앱 프로젝트 내의 뷰들이 볼 수 있도록 게시
Observable 객체 추가
- ObservableObject 프로토콜을 구현하는 데이터 클래스 추가 (New Swift File 생성)
- TimerData 클래스
import Foundation
import Combine
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
}
}
- Timer 인스턴스는 매 초마다 timerDidFire()라는 이름의 함수를 호출하도록 구성
- timerDidFire() 함수는 timerCount 변수에 할당된 값을 1씩 증가시킴
- timerCount 변수는 @Publish 프로퍼티 래퍼로 선언되어 프로젝트 내 뷰에서 관찰 가능
ContentView 레이아웃 설계
import SwiftUI
struct Chap23: View {
@ObservedObject var timerData : TimerData = TimerData()
var body: some View {
**NavigationView {
VStack{
Text("Timer count = \(timerData.timeCount)")
.font(.largeTitle)
.fontWeight(.bold)
.padding()
Button(action: resetCount){
Text("Reset Count")
}
}
}**
}
func resetCount(){
timerData.resetCount()
}
}
동일한 Observable 객체를 접근하는 두 번째 뷰 추가
import SwiftUI
struct SecondView: View {
@ObservedObject var timerData : TimerData
var body: some View {
VStack{
Text("Second View")
.font(.largeTitle)
Text("Timer Count = \(timerData.timeCount)")
.font(.headline)
}
.padding()
}
}
#Preview {
SecondView(timerData: TimerData())
}
- SecondView는 자신만의 TimerData 인스턴스를 가짐 (Timer Count 값이 동일하지 않음)
- ContentView와 SecondView가 동일한 인스턴스를 사용하려면 두 번째 화면으로 이동할 때 첫 번째 뷰에 있는 ObservedObject 객체를 SecondView로 넘겨줘야 함
네비게이션 추가
- ContentView (Chap23) 파일 수정
var body: some View {
NavigationView {
VStack{
Text("Timer count = \(timerData.timeCount)")
.font(.largeTitle)
.fontWeight(.bold)
.padding()
Button(action: resetCount){
Text("Reset Count")
}
NavigationLink(destination: SecondView(timerData: timerData)){
Text("Next Screen")
}
.padding()
}
}
}
→ 두 개의 뷰가 동일한 Observable 객체 인스턴스를 구독하는 것을 확인 가능
Environment 객체 사용
- 앱 내에 여러 뷰가 동일한 구독 객체에 접근할 경우 Environment 객체가 더 효과적
- 두 개의 뷰가 동일한 TimerData 객체에 대한 참조체를 전달하지 않아도 접근 가능
- ContentView(Chap23) 파일 수정
mport SwiftUI
struct Chap23: View {
@EnvironmentObject var timerData : TimerData
var body: some View {
NavigationView {
VStack{
Text("Timer count = \(timerData.timeCount)")
.font(.largeTitle)
.fontWeight(.bold)
.padding()
Button(action: resetCount){
Text("Reset Count")
}
NavigationLink(destination: SecondView()){
Text("Next Screen")
}
.padding()
}
}
}
func resetCount(){
timerData.resetCount()
}
}
#Preview {
Chap23().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()
}
}
#Preview {
SecondView().environmentObject(TimerData())
}
- SceneDelegate.swift 파일 수정 (루트 화면이 생성될 때 TimerData 객체가 Environment 객체 추가)
- iOS 15 이상부터는 사용 x
func scene(_ scene: UIScene, willConnectTo session : UISceneSession,
options connectionOptions : UIScene.ConnectionOptions){
let contentView = ContentView()
let timerData = TimerData()
if let windowScene = scne as? UIWindowScene{
let window = UIWindow(windowScene : windowScene)
window.rootViewController = UIHostingController(rootView: contentView**.environmentObject(timerData))**
self.window = window
window.makeKeyAndVisible()
}
}
'SwiftUI' 카테고리의 다른 글
SwiftUI - 리스트와 내비게이션 (0) | 2024.02.21 |
---|---|
SwiftUI - 스택 정렬과 정렬 가이드 (0) | 2024.02.02 |
SwiftUI - 슬라이더 뷰(Slider View) 사용 (1) | 2024.01.22 |
SwiftUI - 상태 프로퍼티 (State), Observable 객체, Environment 객체 사용 (0) | 2024.01.15 |
SwiftUI - 스택, 프레임 (1) | 2024.01.13 |