본문 바로가기
🍎 iOS/SwiftUI

[SwiftUI] Property Wrappers

by hyebin (Helia) 2024. 4. 4.

Property Wrappers

property wrapper는 프로퍼티에 custom 한 동작을 추가할 수 있는 기능입니다.

프로퍼티에 대한 접근을 래핑 하여 추가 로직이나 동작을 캡슐화 합니다. 이를 통해 코드의 재사용성, 가독성 및 유지 보수성을 향상시킬 수 있습니다.

@State

  • view의 상태를 관리하는 데 사용됩니다.
  • view 내부 데이터가 변경되면 자동으로 view를 업데이트합니다.
  • 가변 값으로 취급되며, 뷰가 생성될 때 해당 값이 초기화되고, 사용자 상호 작용 또는 외부 이벤트에 따라 값이 변경될 수 있습니다.
  • 뷰 내부에서 사용되기 때문에 private으로 선언하는 것을 권장합니다. 
import SwiftUI

struct ContentView: View {
    @State private var count = 0
    
    var body: some View {
        VStack {
            Text("Count: \(count)")
            Button("Increment") {
                count += 1
            }
        }
    }
}

@Binding

  • 데이터의 양방향 바인딩을 가능하게 하는 데 사용됩니다.
  • 상위 @State 변수를 전달받아 하위 뷰에서 캐치해 변화 감지 및 연결합니다.
  • 하나의 소스에서 변경된 데이터를 다른 곳에 전파할 수 있습니다.
  • Binding은 다른 뷰가 소유한 속성을 연결하기에 소유권 및 저장 공간이 없습니다.

부모뷰

import SwiftUI

struct ParentView: View {
    @State private var value = 0
    
    var body: some View {
        ChildView(value: $value)
    }
}

자식뷰

import SwiftUI

struct ChildView: View {
    @Binding var value: Int
    
    var body: some View {
        Button("Increment") {
            value += 1 // 부모 뷰의 상태를 변경
        }
    }
}

@Published

  • ObservableObject로 구현한 클래스 내에서 프로퍼티 선언 시 사용합니다.
  • Published로 선언된 프로퍼티를 뷰에서 관찰 가능합니다.
  • Published로 선언된 프로퍼티는 변경사항을 관찰하고 있는 모든 뷰에 알려주며, 변경될 때마다 자동으로 뷰들을 업데이트합니다.

@ObservedObject

  • 뷰에서 ObservableObject 타입의 인스턴스를 선언 시 사용됩니다.
  • ObservableObject를 준수하는 객체를 뷰에 바인딩하여 해당 객체의 상태 변경을 감지하고, 변경 사항이 발생하면 자동으로 뷰를 업데이트합니다.
import SwiftUI

class Model: ObservableObject {
    @Published var data: String = ""
    
     func updateData(newData: String) {
        data = newData
     }
}

struct ContentView: View {
    @ObservedObject var model = Model()
    
    var body: some View {
        VStack {
            Text("Data: \(model.data)")
            Button("Update Data") {
                model.updateData(newData: "New Data")
            }
        }
    }
}

@StateObject

  • 뷰의 상태를 관리하는 데 사용되는 Property Wrappers입니다.
  • 뷰에서 ObservableObject 타입의 인스턴스를 선언 시 사용합니다.
  • 뷰마다 하나의 인스턴스를 생성하며, 뷰가 사라지기 전까지 같은 인스턴스 유지합니다.
  • ObservedObject의 뷰 렌더링 시 인스턴스 초기화 이슈를 해결하기 위한 방법입니다.
  • SwiftUI가 뷰의 상태를 추적하고 적절하게 관리하므로 메모리 누수 및 예기치 않은 동작을 방지할 수 있습니다.
  • 매번 인스턴스가 새롭게 생성되는 것처럼 외부에서 주입받는 경우가 아닌 최초 생성 선언 시에 사용하는 것이 적절합니다.
import SwiftUI

class ViewModel: ObservableObject {
    @Published var count: Int = 0
    
    func increment() {
        count += 1
    }
}

struct ContentView: View {
    @StateObject var viewModel = ViewModel()
    
    var body: some View {
        VStack {
            Text("Count: \(viewModel.count)")
            Button("Increment") {
                viewModel.increment()
            }
        }
    }
}

@Environment

  • SwiftUI 환경 변수에 접근하여 해당 변수를 읽거나 설정하는 데 사용됩니다.
  • 사용하려는 공유 데이터의 이름을 keyPath로 전달하여 사용합니다.
  • 시스템 공유 데이터는 가변 하기에 var로 선언 필요합니다.
  • 뷰가 생성되는 시점에 값이 자동으로 초기화됩니다.
import SwiftUI

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme
    
    var body: some View {
        Text("Current color scheme: \(colorScheme)")
    }
}

@EnvironmentObject

  • SwiftUI 환경에서 주입된 객체를 읽거나 사용하는 데 사용됩니다.
  • 앱의 여러 뷰에서 동일한 객체에 쉽게 접근할 수 있습니다.
  • 데이터를 뷰 계층 구조를 통해 전파할 수 있으므로, 데이터를 전역적으로 공유하고 관리할 수 있습니다.
  • @EnvironmentObject를 사용하기 위해서는 해당 객체가 앱의 상위 뷰 계층에서 environmentObject(_:) 메서드를 사용하여 환경에 주입되어야 합니다.
import SwiftUI

class UserData: ObservableObject {
    @Published var username = "Guest"
}

struct ContentView: View {
    @EnvironmentObject var userData: UserData
    
    var body: some View {
        VStack {
            Text("Welcome, \(userData.username)!")
            EditUsernameView()
        }
    }
}

struct EditUsernameView: View {
    @EnvironmentObject var userData: UserData
    
    var body: some View {
        TextField("Username", text: $userData.username)
    }
}

struct MainView: View {
    var body: some View {
        ContentView().environmentObject(UserData())
    }
}

 

반응형

'🍎 iOS > SwiftUI' 카테고리의 다른 글

[SwiftUI] Text  (0) 2024.04.18
[SwiftUI] Stack (VStack/HStack/ZStack)  (0) 2024.04.08
[SwiftUI] SwiftUI란?  (0) 2023.03.15

댓글