스유를 시작하면서 사용한 속성들을 정리해보았다.
정리를 시작하면서 든 생각은 엥 사실상 Combine 아니냐 라는 생각이 들었지만 제대로 컴바인과 Rx도 해본적이 없기에..
일단 전체적으로 정리를 해보고 추후 깊게 하나하나 파볼 생각이다.
Property Wrapper
@State - 뷰의 상태를 저장하는 속성
스유에서 상태를 처리하는 방법
뷰의 상태를 저장하는 프로퍼티로 상태관리 주체는 해당 뷰
기본적으로 private 선언이기에 다른 뷰와 값을 소통하려면 Binding을 이용
값이 변경될때마다 UI 업데이트
struct ContentView: View {
@State private var isPlaying: Bool = false
var body: some View
Button(isPlaying? "Pause": "Play") {
isPlaying.toggle)
여기에서 버튼값을 뷰의 상태를 위해 사용되고 이를 토글로 사용할 수 있다. 이는 isPlaying의 상태값이 변경되는 것이고 이렇게 UI가 변경되게 된다
@Binding
- 뷰와 상태를 바인딩 하는 방법
- 상위 @State변수를 전달받아 하위 뷰에서 캐치해 변화감지 및 연결
- Binding은 다른 뷰가 소유한 속성을 연결하기에 소유권 및 저장공간이 없음
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: SisPlaying) //binding
Binding
}
}
}
struct PlayButton: View { // 하위뷰
@Binding var isPlaying: Bool
var body: some View {
Button (isPlaying ?
"Pause" : "Play")
isPlaying. toggle()
ObservableObject
- 클래스 프로토콜로 관찰하는 어떠한 값이 변경되면 변경사항을 알려줌
- 뷰에서 인스턴스 변화를 감시하기 위해 뷰모델 객체로 생성할때 사용할 수 있음
class Contact: ObservableObject {
@Published var name: String
@Published var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1
return age
}
}
let john = Contact(name: "John Appleseed", age: 24)
cancellable = john.objectWillChange
.sink { _ in
print("\\(john.age) will change")
}
print(john.haveBirthday())
@Published
- observableObject를 구현한 클래스 내에서 프로퍼티 선언시 사용
- @Publish로 선언된 프로퍼티를 뷰에서 관찰할 수 있음
- ObservableObject의 ObjectWillChange.send() 기능을 @Published 프로퍼티가 변경되면 자동으로 호출
@ObervableObject
뷰에서 ObervableObject 타입의 인스턴스 선언시 사용
ObervableObject의 값이 업데이트 되면 뷰를 업데이트
class User: ObservableObject {
@Published var age = 10
}
struct ContentView: View {
@ObservedObject var user: User
var body: some View {
Button("Plus Age") {
user.age += 1
}
}
}
@StateObject
뷰에서 ObervableObject 타입의 인스턴스 선언시 사용
뷰마다 하나의 인스턴스를 생성하며, 뷰가 사라지기 전까지 같은 인스턴스 유지
@ObervableObject의 뷰 렌더링시 인스턴스 초기화 이슈 해결위함
매번 인스턴스가 새롭게 생성되는 것처럼 외부에서 주입받는 경우가 아닌 최초 생성선언시에 @StateObject 를 사용하는것이 적절한 방법
@Environment
미리 정의되어 있는 시스템 공유 데이터
사용하려는 공유 데이터의 이름을 KeyPath로 전달하여 사용
시스템 공유 데이터는 가변하기에 var로 선언 필요
뷰가 생성되는 시점에 값이 자동으로 초기화됨
struct ContentView: View {
@Environment(\\.colorScheme) var colorScheme
var body: some View {
Text("Hello, world!")
.foregroundColor(colorScheme == .dark ? .white : .black)
}
}
@EnvironmentObject
ObervableObject를 통해 구현된 타입의 인스턴스를 전역적으로 공유하여 사용
앱 전역에서 공통으로 사용할 데이터를 주입 및 사용
class Info: ObservableObject {
@Published var age = 10
}
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
MainView()
.environmentObject(Info())
}
}
}
struct MainView: View {
@EnvironmentObject var info: Info
var body: some View {
Button(action: {
self.info.age += 1
}) {
Text("Click Me for plus age")
}
SubView()
}
}
struct SubView: View {
@EnvironmentObject var info: Info
var body: some View {
Button(action: {
self.info.age -= 1
}) {
Text("Click Me for minus age")
}
}
}
출처
https://fastcampus.co.kr/dev_online_ios
'IOS - Swift > SwiftUI' 카테고리의 다른 글
[iOS/SwiftUI] SwiftUI에서 특정부분만 UIkit으로 추출해서 사용하기 (0) | 2024.12.03 |
---|---|
[iOS] UIkit + SwiftUI 둘다 사용하기! (1) | 2024.11.27 |
[iOS/SwiftUI] LunchScreen 적용하기 (0) | 2023.12.31 |