inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[Lv.1] iOS 17 앱 개발 기초 - SwiftUI로 시작하기

GallaryView

GalleryView 작성시, @State? @Bidnable? 의 차이점이 뭔지 궁금합니다.

303

ycc3819

작성한 질문수 8

0

IOS17로 업데이트 됨에 따라,

@Observable 매크로를 활용하여 ViewModel을 활용하면,

상태 변화를 감지하여 'View에서 자동적으로 업데이트 된다.'라고 알고 있습니다.

 

@Observable 매크로를 사용해서 코드를 업데이트하던 중 궁금증이 생겨 질문을 남겨봅니다.

 

  1. 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을 사용한다? 라는 내용을 본적이 있습니다.

 

 

  1. 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 매크로를 이용한 예시가 잘 정리되어 있는 문서들이 있을까요?? 제가 잘 이해를 못한 건지, 이 부분이 너무 어렵네요.

 

감사합니다 😀

ios swift swiftui

답변 2

1

Jacob(제이콥)

안녕하세요 ycc3819 님

제가 확인이 늦어 이제 답변드리네요 죄송합니다.

  1. 질문주신 부분과 링크에서 나타난 것은
    @State와 @Observable을 함께 사용할 때 주의할 점은 다음과 같습니다:

     

    @State와 @Observable 사용 시점: @Observable 인스턴스를 생성하는 뷰만 @State를 사용합니다. 다른 뷰에서는 let으로 선언하여 사용합니다.

     

    @Observable을 let으로 선언: 다른 뷰에서 @Observable 인스턴스를 받을 때는 let으로 선언해도 안전합니다. 인스턴스를 소유하는 뷰는 @State를 사용해야 합니다.

     

    이 원칙을 따르면 뷰의 상태 관리와 데이터 흐름이 명확해집니다.
    그렇기 때문에 최소 뷰의 소유권을 가지고 있는 최상위에서는 @State 을 사용하고, 그것을 인스턴스 받어서 사용할때는 let 을 사용하게 이론적으로 안전합니다. 하지만, var 을 사용해도 error 가 발생되거나 그러진 않지만 safe code 을 위해서는 let 사용이 권장되는것입니다.

  2. @State 는 처음 instance 생성할때 viewModel 을 선언할때 사용되며 @Bindable 은 선언된 ViewModel 을 binding 하는 역활을 합니다. 자세한 사항은 iOS17 강의에서 Observation 부분을 참고하시면 됩니다. Project 에서 @Observable 을 사용해서 변환하는것도한 코드 변환 하고 확인 후에 강의및 예제 코드도 조만간 업데이트 하겠습니다.

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다.

SwiftUI에서 @State@Bindable (실제로는 @Binding)의 개념은 데이터의 소유권과 데이터를 어떻게 다루는지에 따라 다릅니다.

  1. @State는 SwiftUI의 View 내부에서 사용되며, View의 상태를 관리하는 데 사용됩니다. 이렇게 선언된 변수는 View가 소유하며, 해당 변수의 값이 변경되면 View는 자동으로 업데이트 됩니다. @State 변수는 주로 View 내에서 private하게 사용되며, 자신이 직접 변경할 수 있는 상태를 다룰 때 사용됩니다.

  2. @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으로 선언하여도 상태 변화를 감지할 수 있습니다. letvar 사이에서의 주요 차이점은 해당 변수의 재할당 가능성에서 나옵니다. @ObservableObject를 사용하는 경우, 객체의 속성이 변경되더라도 객체 자체의 할당을 변경할 필요는 없으므로, let으로 선언하여도 충분합니다.

마지막으로, @Observable에 대한 예시가 잘 정리된 문서를 찾으시는 것 같은데, @ObservableObject 태그와 관련하여 많은 사례와 정보가 공식 Apple 문서SwiftUI 튜토리얼 등에서 찾아볼 수 있습니다. 특히, Apple의 공식 문서와 튜토리얼은 기본적인 사용법부터 심화된 예시까지 잘 설명하고 있어 도움이 될 수 있습니다.

님이 찾으시는 내용과 직접적으로 연관된 자료는 제공한 정보에 포함되어 있지 않으므로, 직접 참고할 수 있는 링크 또는 구체적인 예시 제공은 어렵습니다만, 기본적인 개념 설명으로 도움이 되었기를 바랍니다.

소리가 ㅠㅠ

0

53

2

index와 indexSet

0

59

2

NavigationBarItems Deprecated

0

96

3

Xcode version 문제

0

195

2

페이지 이동에 관해 질문이 있습니다 !

0

339

2

scrollTransition 에서 phase 값을 찍어보고 싶습니다.

0

277

2

갤러리에서 슬라이더 변경시 gridSwitch 가 두번 실행됩니다.

0

307

2

유튜브 영상 플레이시 워닝 이슈 문의

0

518

1

ListBasic 강의 문의 - 딸기 id 오류 및 move 오작동

0

222

1

LazyGrid 강의 문의 - 데이터가 30개 인데 로우가 3줄이면 27개만 노출됨

0

269

1

ScrollView에서 질문 있습니다.

0

286

1

MVVM에서 처음

0

216

1

ExtractView, @Binding 강의에서 .previewLayout(.sizeThatFits) 함수 관련해서 질문드립니다.

0

336

2

iOS 15 버전이후 프리뷰 문제 관련해서 질문드립니다.

0

343

2

VStack으로 프리뷰 생성

0

393

2

MVVM 폴더 안에서 Preview가 작동하지 않습니다.

0

249

1

Preview 질문

0

415

2

LazyGrid 질문 있습니다.

0

337

1

Textfield 입력시 한글 자음 모음 분리 현상이 발생 합니다

1

6531

2

Sheet가 바로 닫히는 문제와 홈 화면 액션 관련 문의

0

288

1

NavigationView를 NavigationStack 으로 변경관련입니다.

1

357

1

Frame 강의에서 다른 결과물이 나와요

0

387

1

Frame에 대한 개념 질문

0

251

1

ShareLink에서 이미지 링크에서 이미지 크기 제한이 있나요?

0

317

2