Swift - Property Wrapper

최조니·2022년 7월 25일
0

Swift

목록 보기
7/10

Property Wrapper

- @State, @Binding, @Published, @ObservedObject


@State

Apple 공식 문서 : State

  • 값을 읽고 쓸 수 있는 property wrapper
  • @State로 선언된 변수의 값이 변할 때 View를 다시 계산하여 출력
  • SwiftUI는 state로 선언된 property들의 저장소를 관리
  • View UI의 현재 상태를 저장하므로 주로 private
  • @State 속성으로 프로퍼티의 초기값을 설정했다면 다른 값으로 재할당 불가
    @Binding 변수를 통해서 가능
import SwiftUI

struct ContentView: View {
    @State private var isEnabled: Bool = false
    
    var body: some View {
        VStack{
            Text(isEnabled ? "True" : "False")
            Button(action: {
                isEnabled.toggle()
            }, label: {
                Text(isEnabled ? "False" : "True")
            })
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

❗️ 만일 isEnabled 변수를 @State 프로퍼티로 지정해주지 않는다면 ?
→ self 변수는 변할 수 없는 값이므로, 사용할 수 없다는 error 발생


@Binding

Apple 공식 문서 : Binding

  • @State 로 선언된 속성을 다른 View에서 사용하기 위해서 @Binding 사용
  • $ 를 통해 Binding 변수임을 표시
  • @State로 선언된 속성에 변경이 생기면 @Binding 변수에서 인지하고 해당 값에 따른 View 변화를 반영
  • 외부에서 접근해야 하므로 private으로 선언하지 않는다.
import SwiftUI

struct ContentView: View {
    @State private var isEnabled: Bool = false
    
    var body: some View {
        VStack{
            Text(isEnabled ? "True" : "False")
            Toggle(isOn: $isEnabled, label: {
                Text(isEnabled ? "False" : "True")
            })
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
import SwiftUI

struct ContentView: View {
    @State private var isEnabled: Bool = false
    
    var body: some View {
        VStack{
            HStack{
                Text("Value: ")
                Text(isEnabled ? "True" : "False")
            }
            NavigationView {
                NavigationLink("check"){
                    CheckView(isEnabled: self.$isEnabled)
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

struct CheckView: View{
    @Binding var isEnabled: Bool
    
    var body: some View {
        Toggle(isOn: $isEnabled, label: {
            Text(isEnabled ? "True" : "False")
        })
        .padding()
    }
}

@ObservedObject

Apple 공식 문서 : ObservedObject

  • Observable object를 구독하고, Observable object가 변할 때마다 view를 무효화한다.

  • 감시 대상 클래스 변수에 선언


@Published

  • 변경을 알릴 변수에 @Published 선언

@Environment

  • 읽기 전용으로 특정 View에서 EnvironmentValues의 특정 요소를 읽어와 View의 구성에 반영할 때 사용
struct ContentView: View {
	@Environment(\.layoutDirection) var layoutDirection
    
    var body: some View {
    	if layoutDirection == .leftToRight {
        	return Text("Left to Right")
		} else {
        	return Text("Right to Left")
		}
	}
}       

Custom Environment

Environment는 시스템에서 제공하는 것만 사용할 수 있는 것이 아닌, 사용자가 직접 앱에 필요한 변수를 추가하고 활용할 수 있다.

  • 환경 키 만들기
    Environment 프로토콜을 채택한 타입을 만들고, defaultValue 타입 프로퍼티를 정의해준다.
    이때 defaultValue는 해당 키에 대한 기봅값으로 활용되고 값의 타입을 결정 짓는다.
private struct CaptionColorKey: EnvironmentKey {
	static let defaultValue = Color(.secondarySystemBackground)
}
  • 환경 확장
    EnvironmentValues 타입에는 실제 사용할 이름의 연산 프로퍼티를 추가한 뒤
    getter / setter를 정의해야 한다.
extension EnviromentValues {
	var captionBackgroundColor: Color {
    	get { self[CaptionColorKey.self] }
        set { self[CaptionColorKey.self] = newValue }
	}
}
  • 뷰 수정자 추가
    필수적인 단계는 아니지만 환경 속성에 대한 뷰 수정자를 추가하면 편리하다.
ContentView()
	.environment(\.captionBackgroundColor, .yellow)
profile
Hello zoni-World ! (◍ᐡ₃ᐡ◍)

0개의 댓글