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 |
댓글