
앞 게시물 ObservedObject를 먼저 보고 오시는것을 추천합니다. 이번 게시물에서는 앞에서 썼던 코드를 재사용 합니다.
이번에는 EnvironmentObject
에 대해 알아보도록 하겠습니다.
EnvironmentObject
앱의 많은 뷰와 공유해야하는 데이터의 경우 SwiftUI
는 EnvironmentObject
속성 래퍼를 제공합니다.
이를 통해 필요한 곳 어디에서나 모델 데이터를 공유 할 수 있으며, 데이터가 변경 될 때 뷰가 자동으로 업데이트 된 상태로 유지됩니다.
A View
에서 데이터를 생성 후 👉🏻 B View
👉🏻 C View
로 전달 후, 최종적으로 👉🏻 D View
로 전달하는 대신에, 특정 뷰에서 데이터를 생성 후 B,C,D
가 전달 없이 공용으로 사용 가능 하게 할 수 있습니다.
그리고 EnvironmentObject
를 사용하면 @ObservedObject
를 사용하지 않아도 됩니다.
프로젝트를 함께 만들어보며 알아보도록 하겠습니다.
앞 게시물에서 사용했던 Score
코드를 그대로 가져와서 새로운 Score
버튼을 만들고, 두 버튼중 어느것을 누르던 두 버튼에 모두 값이 증가하도록 만들어 보겠습니다.
새로운 SwiftUI
파일을 만들어 이름은 'MyScoreView
'라고 정해주고, UserSetting
에서 정의했던 score
을 바인딩해서 가져오겠습니다. 그리고 score
값이 증가하는 값을 만들고 아래와같이 코드를 작성해줍니다.
//MyScoreView import SwiftUI struct MyScoreView: View { //UserSetting의 score을 바인딩해서 가져옴 @Binding var score: Int var body: some View { VStack { Text("\(self.score)") Button("클릭시 score 증가") { self.score += 1 } .padding() .background(Color.orange) .foregroundColor(.black) } .padding() .background(Color.yellow) } } struct MyScoreView_Previews: PreviewProvider { static var previews: some View { //바인딩해온 값을 .constant값으로 설정 MyScoreView(score: .constant(0)) } }

자, 이렇게 버튼을 만들어줬고 이제 ContentView
에 MyScoreView
를 추가해주겠습니다.
MyScoreView()
를 그냥 가져오면 당연히 컴파일 오류가 생깁니다. 이유는 바인딩해서 가져오는 값이기 때문에 매겨변수를 반드시 가져와야 합니다. 달러($
)표시는 필수겠죠?
//ContentView import SwiftUI struct ContentView: View { @ObservedObject var userSetting = UserSetting() var body: some View { VStack { Text("\(self.userSetting.score)") .font(.largeTitle) Button("클릭시 score 상승") { self.userSetting.score += 1 } //구분선 추가 Divider() .padding() //바인딩해서 가져오기때문에 $표시 MyScoreView(score: self.$userSetting.score) } } }
이렇게 까지 코드를 작성하면 아래와 같은 화면을 볼 수 있습니다.

그런데 이렇게 코드를 전달 전달 전달 하면 코드도 너무 길어지고 복잡해지지 않나요?? 😭
동일한 작업을 수행하는 훨씬 더 나은 접근이 있습니다. 이럴때 사용하는것이 바로 EnvironmentObject
입니다. 위에서 공동으로 사용되었던 UserSetting
의 'Score
'을 공통 위치에 두어 둘다 엑세스 할 수 있게 하는거죠!
그렇다면 어떻게 사용해야 할까요?
첫번째
SceneDelegate.swift
파일을 클릭해서 들어가줍니다. ScenDelegate
내부에서 수정해야할 곳은 이곳입니다.

보시면 contentView = ContentView()
로 지정되어있죠? 그렇기 때문에 프로젝트 내부에서 어떠한 Swift
파일을 만들어도 ContentView
를 엑세스 할 수 있는것입니다. :)

두번째
userSetting
변수를 추가해줍니다.
//SceneDelegate let contentView = ContentView() // Use a UIHostingController as window root view controller. if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) //userSetting을 contentView에 전달해줌 let userSetting = UserSetting() window.rootViewController = UIHostingController(rootView: contentView) self.window = window window.makeKeyAndVisible() } }
userSetting
을 이제 contentView
에 전달 할 수 있지만 생성자가 아닙니다. 추가해야 할 코드가 더 있습니다.
window.rootViewController = UIHostingController(rootView: contentView)
rootView: contentView
바로 뒤에 EnvironmentObject
를 반드시 추가해줘야 합니다.

let userSetting = UserSetting() window.rootViewController = UIHostingController(rootView: contentView.environmentObject(userSetting))
이 작업이 완료되었으면 ContentView
로 돌아가서 @ObservedObject
객체를 @EnvironmentObject로 대체해줘야 합니다.
//ContentView struct ContentView: View { //@ObservedObject var userSetting = UserSetting()를 아래와같이 수정 @EnvironmentObject var userSetting: UserSetting var body: some View { VStack { Text("\(self.userSetting.score)") .font(.largeTitle) Button("클릭시 score 상승") { self.userSetting.score += 1 } Divider() .padding() /*MyScoreView(score: self.$userSetting.score)를 아래와같이 수정 MyScoreView의 바인딩을 Environment로 수정해줘야함*/ MyScoreView() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { //.environmentObject(UserSetting()) 추가 ContentView().environmentObject(UserSetting()) } }
MyScoreView
도 @Binding
을 삭제하고 EnvironmentObject
로 수정하고 나머지 부분도 아래와같이 수정합니다.
//MyScoreView import SwiftUI struct MyScoreView: View { //before : @Binding var score: Int @EnvironmentObject var userSetting: UserSetting var body: some View { VStack { // before : Text("\(self.score)") Text("\(self.userSetting.score)") Button("클릭시 score 증가") { //before : self.score += 1 self.userSetting.score += 1 } .padding() .background(Color.orange) .foregroundColor(.black) } .padding() .background(Color.yellow) } } struct MyScoreView_Previews: PreviewProvider { static var previews: some View { //before : MyScoreView(score: .constant(0)) MyScoreView().environmentObject(UserSetting()) } }

읽어주셔서 감사합니다🤟
본 게시글의 전체코드 GitHub 👇🏻
Seogun95/SwiftUI_EnvironmentObject_TUT
EnvironmentObject에 대해 알아봅시다. Contribute to Seogun95/SwiftUI_EnvironmentObject_TUT development by creating an account on GitHub....
github.com
'SWIFTUI > Grammar' 카테고리의 다른 글
SwiftUI : @Environment 프로퍼티 래퍼 (0) | 2021.04.06 |
---|---|
SwiftUI : EnvironmentValues (0) | 2021.04.05 |
SwiftUI : #2 MVVM의 간단한 예제 (1) | 2021.02.17 |
SwiftUI : #1 디자인 패턴 과 MVVM (Design Patterns and MVVM) (0) | 2021.02.15 |
SwiftUI : #2 ObservedObject '클릭시 값 증가' (0) | 2021.02.14 |