작성
·
140
·
수정됨
0
IOS17로 업데이트 됨에 따라,
@Observable 매크로를 활용하여 ViewModel을 활용하면,
상태 변화를 감지하여 'View에서 자동적으로 업데이트 된다.'라고 알고 있습니다.
@Observable 매크로를 사용해서 코드를 업데이트하던 중 궁금증이 생겨 질문을 남겨봅니다.
ContentView, VideoView에서 AnimalViewModel의 인스턴스를 갖고 있을 때, var로 정의했을 때와 let으로 정의를 했을 때의 차이점이 있을까요?
struct ContentView: View {
// let이나 var이나 상관없는가?
let vm: AnimalViewModel
var body: some View {
NavigationStack{
List{
// 1. Cover Image - hero Image
CoverImageView(vm: vm)
관련내용을 공부하다보니, 해당 링크에서
https://www.donnywals.com/comparing-observable-to-observableobjects/
"Defining an @Observable
as a let
property" 부분에
HomeView에서 ViewModel에 @State 프로퍼티 래퍼를 사용한 후 let을 사용한다? 라는 내용을 본적이 있습니다.
GalleryView에서 @State 프로퍼티 래퍼와 @Bindable 프로퍼티 래퍼를 사용했을 때의 차이점이 뭘까요 ㅠㅠ .
우선, @State로 했을 때는 변화의 감지를 HomeView에서도 GalleryView에서도 잘 작동하여, 슬라이더를 변화시켰을 때 Grid의 개수가 바뀝니다.
하지만 @Bindable 프로퍼티 래퍼를 사용했을 때에는 GalleryView에서만 슬라이더 변화를 감지 하고, HomeView에서는 변화를 감지하지 못하는 상황이 벌어집니다.
@State var vm: AnimalViewModel
@Bindable var vm: AnimalViewModel
struct GallaryView: View {
@State var vm: AnimalViewModel
var body: some View {
NavigationStack{
ScrollView(.vertical, showsIndicators: false){
VStack(spacing: 30){
// 1. Image
Image(vm.selectedAnimal)
.resizable()
.scaledToFill()
.frame(width: 250, height: 250)
.clipShape(Circle())
.overlay(Circle().stroke(Color.accentColor, lineWidth: 5))
// 2. Slider
Slider(value: $vm.gridColumn, in: 2...4, step: 1)
.padding(0)
.onChange(of: vm.gridColumn) {
withAnimation(Animation.easeInOut(duration: 1.0)){
vm.gridSwitch()
}
}
// 3. Grid
LazyVGrid(columns: vm.gridLayout, spacing: 20){
ForEach(vm.animals){ animal in
Image(animal.image)
.resizable()
.scaledToFill()
.frame(width: 80, height: 80)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 1))
.onTapGesture {
withAnimation(Animation.spring()){
vm.selectedAnimal = animal.image
}
}
}
}
} //:VSTACK
.padding()
} //:SCROLL
.navigationTitle("갤러리")
.navigationBarTitleDisplayMode(.inline)
} //:NAVIGATION
}
}
추가로,
@Observable 매크로를 이용한 예시가 잘 정리되어 있는 문서들이 있을까요?? 제가 잘 이해를 못한 건지, 이 부분이 너무 어렵네요.
감사합니다 😀
답변 2
1
안녕하세요 ycc3819 님
제가 확인이 늦어 이제 답변드리네요 죄송합니다.
질문주신 부분과 링크에서 나타난 것은
@State와 @Observable을 함께 사용할 때 주의할 점은 다음과 같습니다:
• @State와 @Observable 사용 시점: @Observable 인스턴스를 생성하는 뷰만 @State를 사용합니다. 다른 뷰에서는 let으로 선언하여 사용합니다.
• @Observable을 let으로 선언: 다른 뷰에서 @Observable 인스턴스를 받을 때는 let으로 선언해도 안전합니다. 인스턴스를 소유하는 뷰는 @State를 사용해야 합니다.
이 원칙을 따르면 뷰의 상태 관리와 데이터 흐름이 명확해집니다.
그렇기 때문에 최소 뷰의 소유권을 가지고 있는 최상위에서는 @State 을 사용하고, 그것을 인스턴스 받어서 사용할때는 let 을 사용하게 이론적으로 안전합니다. 하지만, var 을 사용해도 error 가 발생되거나 그러진 않지만 safe code 을 위해서는 let 사용이 권장되는것입니다.
@State 는 처음 instance 생성할때 viewModel 을 선언할때 사용되며 @Bindable 은 선언된 ViewModel 을 binding 하는 역활을 합니다. 자세한 사항은 iOS17 강의에서 Observation 부분을 참고하시면 됩니다. Project 에서 @Observable 을 사용해서 변환하는것도한 코드 변환 하고 확인 후에 강의및 예제 코드도 조만간 업데이트 하겠습니다.
0
안녕하세요, 인프런 AI 인턴입니다.
SwiftUI에서 @State
와 @Bindable
(실제로는 @Binding
)의 개념은 데이터의 소유권과 데이터를 어떻게 다루는지에 따라 다릅니다.
@State
는 SwiftUI의 View 내부에서 사용되며, View의 상태를 관리하는 데 사용됩니다. 이렇게 선언된 변수는 View가 소유하며, 해당 변수의 값이 변경되면 View는 자동으로 업데이트 됩니다. @State
변수는 주로 View 내에서 private하게 사용되며, 자신이 직접 변경할 수 있는 상태를 다룰 때 사용됩니다.
@Binding
은 부모 View로부터 전달받은 데이터를 참조하며, 이 데이터의 변경 사항을 부모 View에도 반영하고 싶을 때 사용됩니다. 즉, @State
를 사용하여 부모 View에서 관리되는 상태를 자식 View로 전달하고 싶을 때, @State
변수를 @Binding
변수로 변환하여 자식 View로 전달합니다. 이를 통해 자식 View에서 변경된 내용이 부모 View로 전파되어 상태가 동기화됩니다.
GalleryView와 HomeView 사이에서 발생하는 상황을 보면, @State
를 사용한 경우 GalleryView에서 상태 변경이 잘 감지되는 것은 해당 View가 직접 상태를 소유하고 있기 때문입니다. 반면, @Bindable
(@Binding
이 맞는 표현)을 사용하면, GalleryView는 상태의 변화를 감지할 수 있지만, 이 변화가 HomeView로 전파되려면 HomeView 또한 이 상태를 관리하고 있어야 하며, GalleryView에 이 상태를 @Binding
을 통해 전달해야 합니다.
ContentView, VideoView에서 AnimalViewModel
의 인스턴스를 let
으로 정의했을 때와 var
으로 정의했을 때의 차이점에 관한 질문에 대해서는, SwiftUI의 View는 불변(immutable)이라는 특성을 가지고 있기 때문에, @Observable
객체를 let
으로 선언하여도 상태 변화를 감지할 수 있습니다. let
과 var
사이에서의 주요 차이점은 해당 변수의 재할당 가능성에서 나옵니다. @ObservableObject
를 사용하는 경우, 객체의 속성이 변경되더라도 객체 자체의 할당을 변경할 필요는 없으므로, let
으로 선언하여도 충분합니다.
마지막으로, @Observable
에 대한 예시가 잘 정리된 문서를 찾으시는 것 같은데, @ObservableObject
태그와 관련하여 많은 사례와 정보가 공식 Apple 문서나 SwiftUI 튜토리얼 등에서 찾아볼 수 있습니다. 특히, Apple의 공식 문서와 튜토리얼은 기본적인 사용법부터 심화된 예시까지 잘 설명하고 있어 도움이 될 수 있습니다.
님이 찾으시는 내용과 직접적으로 연관된 자료는 제공한 정보에 포함되어 있지 않으므로, 직접 참고할 수 있는 링크 또는 구체적인 예시 제공은 어렵습니다만, 기본적인 개념 설명으로 도움이 되었기를 바랍니다.