SWIFTUI/Grammar

SwiftUI : @Environment 프로퍼티 래퍼

서근 2021. 4. 6. 15:01
반응형

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

.previewLayout(.sizeThatFits)

 

 

읽어주셔서 감사합니다🤟