λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
🍎 iOS/SwiftUI

[iOS] SwiftUI property wrapper @State @Binding

by Danna 2022. 6. 2.
728x90
728x90

@State


SwiftUI λŠ” state 둜 μ„ μ–Έν•œ ν”„λ‘œνΌν‹°μ˜ μ €μž₯μ†Œλ₯Ό κ΄€λ¦¬ν•œλ‹€. ν•΄λ‹Ή ν”„λ‘œνΌν‹°μ˜ 값이 변경될 λ•Œ, SwiftUI λŠ” 값에 μ˜μ‘΄ν•˜κ³  μžˆλŠ” λ·° κ³„μΈ΅κ΅¬μ‘°μ˜ 뢀뢄을 μ—…λ°μ΄νŠΈν•œλ‹€. State ν”„λ‘œνΌν‹°λŠ” ν•˜λ‚˜μ˜ λ·° μ•ˆμ—μ„œ μ‚¬μš©λ˜λŠ” κ°’μœΌλ‘œ, 일반적으둜 private ν‚€μ›Œλ“œλ₯Ό λΆ™μ—¬μ„œ μ‚¬μš©ν•œλ‹€. 

 

State instance λŠ” κ°’(value)을 읽고 μ“Έ 수 μžˆλŠ” ν˜•νƒœμ΄κΈ° λ•Œλ¬Έμ—, value 와 λ™μΌν•˜μ§€λŠ” μ•Šλ‹€. state κ°€ κ°–κ³ μžˆλŠ” value 에 μ•‘μ„ΈμŠ€ν•˜κΈ° μœ„ν•΄μ„œλŠ”, property name 을 톡해 μ ‘κ·Όν•˜λ©΄ λœλ‹€. ν•΄λ‹Ή 값은 wrappedValue 속성을 λ°˜ν™˜ν•œλ‹€. wrappedValue λŠ” state λ³€μˆ˜κ°€ μ €μž₯ν•˜κ³  μžˆλŠ” 값을 μ ‘κ·Όν•˜λŠ” ν”„λ‘œνΌν‹°μ΄μ§€λ§Œ, wrappedValue λ₯Ό 직접 μ ‘κ·Όν•΄μ„œλŠ” μ•ˆλœλ‹€. 

 

μ•„λž˜ μ˜ˆμ œλŠ” PlayButton view μ—μ„œ isPlaying μ΄λΌλŠ” state property λ₯Ό μ°Έμ‘°ν•΄μ„œ, 값을 읽고 μ—…λ°μ΄νŠΈν•˜λŠ” μ˜ˆμ œμ΄λ‹€. Button label 은 isPlaying 값에 따라 Pause, Play λ₯Ό μ§€μ •ν•˜κ³  있고, λ²„νŠΌμ„ λˆ„λ₯Όλ•Œ μ•‘μ…˜μœΌλ‘œ isPlaying 값을 ν† κΈ€μ‹œν‚€κ³  μžˆλ‹€.

 

struct PlayButton: View {
    @State private var isPlaying: Bool = false

    var body: some View {
        Button(isPlaying ? "Pause" : "Play") {
            isPlaying.toggle()
        }
    }
}

 

 

@Binding


State λ³€μˆ˜λ₯Ό μžμ‹λ·°λ‘œ 전달할 경우, SwiftUI λŠ” λΆ€λͺ¨λ·°μ—μ„œ state λ³€μˆ˜μ˜ 값이 변경될 λ•Œ μžμ‹λ·°μ—κ²Œ μ „λ‹¬ν•˜μ§€λ§Œ, μžμ‹λ·°λ₯Ό 값을 직접 λ³€κ²½ν•  수 μ—†λ‹€. μžμ‹λ·°μ—μ„œ State λ³€μˆ˜μ˜ 값을 μˆ˜μ •ν•  수 있게 ν•˜λ €λ©΄ Binding λ³€μˆ˜λ₯Ό μ „λ‹¬ν•΄μ•Όν•œλ‹€. ν”„λ‘œνΌν‹° 이름 μ•žμ— λ‹¬λŸ¬ν‘œμ‹œ($) λ₯Ό 뢙이면, state value 에 λŒ€ν•œ binding 인 projectedValue 을 λ°›μ•„μ˜¬ 수 μžˆλ‹€. 

πŸ–‹ μ •λ¦¬ν•˜μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€
propertyName 으둜 μ ‘κ·Όμ‹œ Value νƒ€μž…μΈ wrappedValue λ₯Ό λ°˜ν™˜ν•œλ‹€.
$propertyName 으둜 μ ‘κ·Όμ‹œ Binding<Value> νƒ€μž…μΈ projectedValue λ₯Ό λ°˜ν™˜ν•œλ‹€.

 

μ•„λž˜ μ˜ˆμ œλŠ” μœ„μ˜ PlayButton View μ—μ„œ State ν”„λ‘œνΌν‹°λ₯Ό Binding ν”„λ‘œνΌν‹°λ‘œ λ³€κ²½ν•œ μ˜ˆμ œμ΄λ‹€. PlayButton λ·°κ°€ PalyerView 의 μžμ‹λ·°λ‘œ μ‚¬μš©λ  κ²½μš°μ— State 을 μ΄μš©ν•œλ‹€λ©΄ λΆ€λͺ¨λ·°λ‘œ 전달할 수 μ—†κΈ° λ•Œλ¬Έμ—, Binding 으둜 λ³€κ²½ν•΄ λΆ€λͺ¨λ·°μ˜ state 와 μ—°κ²°ν•΄μ€€ 것이닀.

 

PlayerView μ—μ„œ PlayButton 을 μƒμ„±ν•˜λŠ” μ½”λ“œλ₯Ό 보면 $isPlaying 으둜 State λ³€μˆ˜μ˜ projectedValue λ₯Ό μ „λ‹¬ν•˜κ³  μžˆλ‹€. State 둜 μ„ μ–Έν•œ isPlaying 의 νƒ€μž…μ΄ Bool μ΄λ―€λ‘œ, $isPlaying 둜 λ°˜ν™˜λ˜λŠ” projectedValue μ˜ νƒ€μž…μ€ Binding<Bool> 이 λœλ‹€. 

 

struct PlayButton: View {
    @Binding var isPlaying: Bool

    var body: some View {
        Button(isPlaying ? "Pause" : "Play") {
            isPlaying.toggle()
        }
    }
}

struct PlayerView: View {
    var episode: Episode
    @State private var isPlaying: Bool = false

    var body: some View {
        VStack {
            Text(episode.title)
                .foregroundStyle(isPlaying ? .primary : .secondary)
            PlayButton(isPlaying: $isPlaying) // Pass a binding.
        }
    }
}

 

참고둜, View λ₯Ό μΈμŠ€ν„΄μŠ€ν™” ν•˜λŠ” λ·° κ³„μΈ΅μ—μ„œ state property λ₯Ό μ΄ˆκΈ°ν™”ν•˜λ©΄ μ•ˆλœλ‹€. SwiftUI κ°€ μ œκ³΅ν•˜λŠ” μŠ€ν† λ¦¬μ§€ 관리와 μΆ©λŒν•  수 있기 λ•Œλ¬Έμ΄λ‹€. 이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄μ„œ State λŠ” 항상 private 으둜 μ„ μ–Έν•˜κ³ , ν•΄λ‹Ή 값에 접근이 ν•„μš”ν•œ λ·° κ³„μΈ΅μ˜ μ΅œμƒλ‹¨ 뷰에 State λ₯Ό λ°°μΉ˜ν•΄μ•Όν•œλ‹€.

 

λ˜ν•œ, Binding ν”„λ‘œνΌν‹°λ₯Ό 생성할 λ•Œμ—λŠ” μ΄ˆκΈ°κ°’μ„ 지정할 수 μ—†λ‹€. Binding 은 원본인 State 의 값을 μ—°κ²°ν•˜λŠ” 역할을 ν•˜κΈ° λ•Œλ¬Έμ—, νƒ€μž…λ§Œ 지정할 수 μžˆλ‹€. Binding ν”„λ‘œνΌν‹°λ₯Ό κ°–λŠ” View 의 μƒμ„±μžμ—μ„œλŠ” ν•„μˆ˜λ‘œ Binding μΈμžμ— 값을 μ§€μ •ν•΄μ€˜μ•Όν•œλ‹€.

 

State ν”„λ‘œνΌν‹°μ˜ 값을 λ³€κ²½ν•˜λŠ” 것은 thread-safe ν•˜λ‹€.

 

 

πŸ“„ μ°Έκ³  λ¬Έμ„œ

 

728x90
728x90