SwiftUI

[SwiftUI] @EnvironmentObject 프로퍼티 래퍼 실습 튜토리얼 예제


Environment 객체

구독(Observable) 객체와 달리 Environment 객체는 뷰에서 뷰로 전달할 필요 없이 모든 뷰가 접근할 수 있다는 것이다.
Environment 객체를 구독해야 하는 객체는 @ObservedObject 래퍼 대신에 @EnvironmentObject 프로퍼티 래퍼를 이용하여 해당 객체를 참조하면 된다.

@EnvironmentObject var demoData: DemoData

 

[TimerData.swift]

이 클래스는 ObservableObject 프로토콜을 구현하는 것으로 선언되었다.

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

 

 

[ContentView .swift] 레이아웃 설계하기

import SwiftUI

struct ContentView: View {
    
//    @ObservedObject var timerData: TimerData = TimerData()
    @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 Counter")
                }
                
                //내비게이션 링크 추가
                NavigationLink(destination:
//                                SecondView(timerData: timerData)) {
                               SecondView()) {
                    Text("Next Screen")
                }
                .padding()
            }
        }
 
    }
    
    func resetCount() {
        timerData.resetCount()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
//        ContentView()
        ContentView().environmentObject(TimerData())
    }
}

[SecondView.swift] 레이아웃 설계하기

import SwiftUI

struct SecondView: View {
    
//    @ObservedObject var timerData: TimerData
    @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())
    }
}

교재에는 SceneDelegate.swift 파일을 수정하여 루트(root) 화면이 생성될 때

TimerData 객체가 Environment 객체에 추가되도록 한다고 나와 있지만

최신버전의 Xcode툴에서 SwiftUI 프로젝트 생성시 SceneDelegate.swift파일은 존재하지 않는다.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
	options connectionOptions: UIScene.ConnectionOptions) {
 
    let contentView = ContentView()    
    
    let timerData = TimerData()   
    
    if let windowScene = scene as? UIWindowScene {        
        let window = UIWindow(windowScene: windowScene)
        
        window.rootViewController = UIHostingController(rootView:          
        	contentView.environmentObject(timerData))
            
        self.window = window        
        window.makeKeyAndVisible()    
	}
}

-알라딘 eBook <핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍> (닐 스미스 지음, 황반석 옮김) 중에서

 

그래서 @main이 선언되어 있는 swift 파일에 추가해주었더니 정상적으로 동작을 하였다.

근데 이렇게 하는게 맞나?

import SwiftUI

@main
struct ObservableDemoApp: App {
    
    //추가
    let timerData = TimerData()

    var body: some Scene {
        WindowGroup {
        	//ContentView()
            //변경
            ContentView().environmentObject(timerData)
        }
    }
}

 

[참고 자료]

-알라딘 eBook <핵심만 골라 배우는 SwiftUI 기반의 iOS 프로그래밍> (닐 스미스 지음, 황반석 옮김) 중에서

 

Leave a Reply

error: Content is protected !!