SwiftUI : @Environment 프로퍼티 래퍼
Environment
에 대해 알아보도록 합시다.
Environment
앞에서 다룬 Environment
수식어가 뷰의 환경 요소를 변경시키기 위한 쓰기 전용의 기능이었다면, 이번에 볼 @Environment
라는 프로퍼티 래퍼는 읽기 전용으로 특정 뷰에서 EnvironmentValues
의 특정 요소를 읽어와 뷰 구성에 반영할 때 사용합니다.
예를 들어, 영어, 한국어, 중국어와 같이 일반적으로 사용되는 LTR(Left to Right)
환경과 아랍어나 히브리어처럼 중동지역에서 사용되는 RTL(Right to Left)
언어 환경에서 뷰를 서로 다르게 표현하고 싶다고 가정해보겠습니다.
이럴 땐 Environment
를 사용하여 여러가지 환경 변수 중 layoutDirection
을 선택하고, 레이아웃 방향에 대한 환경 정보를 읽어와 처리할 수 있습니다.
struct ContentView : View {
@Environment(\.layoutDirection) var layoutDirection
var body: some View {
if layoutDirection == .leftToRight {
return Text("Let to Right") //LTR 언어 환경에서 사용
//출력
} else {
return Text("Right to Left") //RTL 언어 환경에서 사용
//출력
}
}
}
Custom Environment
Environment
는 시스템에서 제공하는 것만 사용할 수 있는 게 아닙니다. 사용자가 직접 앱에 필요한 변수를 추가하고 활용 할 수 있습니다.
1. 환경 키 만들기
이것을 사용 하기 위해서는 Environment
프로토콜을 채택한 타입을 만들고, defaultValue
타입 프로퍼티를 정의해줘야 합니다. 이 defaultValue
는 해당 키에 대한 기본값으로 활용되고 값의 타입을 결정짓습니다.
private struct CaptionColorKey: EnvironmentKey {
static let defaultValue = Color(.secondarySystemBackground)
}
2. 환경 확장
EnvironmentValues
타입에 우리가 실제 사용할 이름의 연산 프로퍼티를 추가한 뒤, getter
, setter
를 정의해야 합니다.
extension EnvironmentValues {
var captionBackgroundColor: Color {
get { self[CaptionColorKey.self] }
set { self[CaptionColorKey.self] = newValue }
}
}
3. 뷰 수정자 추가 (선택사항)
이 단계는 필수는 아니지만 환경 속성에 대한 뷰 수정자를 추가하는 것이 편리할 수 있습니다.
ContentView()
.environment(\.captionBackgroundColor, .yellow)
또는, View
속성에 대한 Extension
을 추가 하여 더 보기 좋게 만들 수 도 있습니다.
extension View {
func captionBackgroundColor(_ color: Color) -> some View {
environment(\.captionBackgroundColor, color)
}
}
ContentView()
.captionBackgroundColor(.yellow)
4. 사용
Key
를 정의한 후 사용하는 것은 Apple
에서 제공 한 환경 키와 동일합니다. @Environment
속성 래퍼를 사용하여 환경에서 값을 가져옵니다.
@Environment(\.captionBackgroundColor) var backgroundColor
이제 배경색을 설정하는 수정자를 추가해주겠습니다.
import SwiftUI
struct Caption: ViewModifier {
let font: Font
@Environment(\.captionBackgroundColor) var backgroundColor
func body(content: Content) -> some View {
content
.font(font)
.padding([.leading, .trailing], 5.0)
.background(backgroundColor)
.cornerRadius(5.0)
}
}
extension View {
func caption(font: Font = .caption) -> some View {
modifier(Caption(font: font))
}
}
전체 코드
위 Environment
를 사용한 코드를 보자면 아래와 같습니다.
<hide/>
import SwiftUI
// 1. 기본값으로 키 생성
private struct CaptionColorKey: EnvironmentKey {
static let defaultValue = Color(.secondarySystemBackground)
}
// 2. 속성을 통해 환경 확장
extension EnvironmentValues {
var captionBackgroundColor: Color {
get { self[CaptionColorKey.self] }
set { self[CaptionColorKey.self] = newValue }
}
}
// 3. 뷰 수정자 추가(선택사항)
extension View {
func captionBackgroundColor(_ color: Color) -> some View {
environment(\.captionBackgroundColor, color)
}
}
// 4. Environment에 의존하여 배경색을 설정하는 수정자
struct Caption: ViewModifier {
let font: Font
@Environment(\.captionBackgroundColor) var backgroundColor
func body(content: Content) -> some View {
content
.font(font)
.padding([.leading, .trailing], 5.0)
.background(backgroundColor)
.cornerRadius(5.0)
}
}
extension View {
func caption(font: Font = .caption) -> some View {
modifier(Caption(font: font))
}
}
// ContentView
struct ContentView : View {
var body: some View {
Text("서근 개발블로그")
.caption(font: .largeTitle)
.captionBackgroundColor(.yellow)
}
}
읽어주셔서 감사합니다🤟