관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - SwiftUI] Redacted(reason:), skeleton 모자이크 사용 방법 본문

iOS 기본 (SwiftUI)

[iOS - SwiftUI] Redacted(reason:), skeleton 모자이크 사용 방법

jake-kim 2022. 11. 5. 23:46

목차) SwiftUI의 기본 - 목차 링크

Redacted 란

* redact: (민감한 정보를) 수정하다

  • 어떤 정보를 수정할 때, 관련 이유를 redacted(reason:) 파라미터로 넣으면 그에 따른 UI를 보여주는 메소드
  • (스켈레톤 뷰처럼 뷰의 내용을 가려서 보여주는 것)

https://developer.apple.com/documentation/SwiftUI/View/redacted(reason:)

  • 파라미터로 들어갈 수 있는 값은 .placeholder와 .privacy 존재

.redacated(reason: .placeholder) 사용 방법

ex) 프로필 뷰를 보여줄 때 api 로딩 전에 placeholder를 보여주고 싶은 경우 사용

  • 프로필 뷰 구현

profileView

struct ContentView: View {
  @State var isLoading = true
  
  var body: some View {
  	profileView
  }
  
  @ViewBuilder
  var profileView: some View {
    VStack {
      Image(systemName: "person.fill")
        .resizable()
        .frame(width: 50, height: 50)
        .foregroundColor(.black)
      Text("jake")
        .foregroundColor(.black)
      Button("Tap!") {
        print("Tap information")
      }
      .disabled(isLoading) // redacted를 해도 disabled되지 않으므로 명시적으로 disabled 설정 필요
    }
  }
}

* 주의할점: redacted를 적용해서 뷰를 스켈리톤처럼 보여주더라도 버튼같은 경우 .disabled()를 명시적으로 해주지 않으면 disable가 안되므로 주의

  • redacted(reason:) 추가하여 구현
    • 예시를 위해서 DispatchQueue.main.asyncAfter로 3초 있다가 isLoading이 끝난다고 구현
    • redcated를 다시 비활성화 할댄 reason 파라미터에 []를 주입
var body: some View {
  profileView
    .redacted(reason: isLoading ? .placeholder : [])
    .onAppear {
      DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        self.isLoading = false
      }
    }
}

3초 있다가 뷰 노출

.redacated(reason: .privacy) 사용 방법

  • redactionReasons라는 내부적으로 정의된 Environment와 같이 사용
  • .privacy는 내부적으로 privacy라는 상태를 저장해놓는 역할
    • 환경변수 redactionReasons에 접근하여, privacy를 포함하는지 체크하여 분기문을 태워 뷰 표출
// .privacy 주입
MyView()
  .redacted(reason: .privacy)
  
// redactionReasons 환경 변수에 접근하여 privacy인지 판별
struct MyView: View {
  @Environment(\.redactionReasons) var redactionReasons

  var body: some View {
    if redactionReasons.contains(.privacy) {
      Text("This is privacy")
    } else {
      Text("This is public")
    }
  }
}

.privacy 주입했으므로 privacy 텍스트 표출

커스텀 RedactionReasons

  • 위와같이 .redacted(reason:)으로 RedactionReasons 값을 주입하고, 뷰에서 readactionReasons 환경 변수에 접근하여 분기문을 태워서 사용하는데, 이때 .privacy 값 말고도 다른 값 정의해서 사용도 가능
    • rawValue는 일종의 id이므로, 중복되지 않도록 2의 제곱으로 표현
extension RedactionReasons {
  static let someReason = RedactionReasons(rawValue: 1 << 2) // 4
  static let someReason2 = RedactionReasons(rawValue: 1 << 4) // 16
}

* 사용하는쪽

// 사용하는쪽
MyView()
  .redacted(reason: .someReason)
MyView()
  .redacted(reason: .someReason2)
  
// 분기문
struct MyView: View {
  @Environment(\.redactionReasons) var redactionReasons

  var body: some View {
    if redactionReasons.contains(.privacy) {
      Text("This is privacy")
    } else if redactionReasons.contains(.someReason) {
      Text("This is someReason")
    } else if redactionReasons.contains(.someReason2) {
      Text("This is someReason2")
    } else {
      Text("This is public")
    }
  }
}

결과 - reason값에 따라 분기문 정상 동작


* 전체 코드: https://github.com/JK0369/ExRedacted-SwiftUI

* 참고

https://developer.apple.com/documentation/swiftui/redactionreasons

https://developer.apple.com/documentation/SwiftUI/View/redacted(reason:) 

Comments