상태를 누가 소유하고 어떻게 전달해야 하는가

SwiftUI에서는 상태를 저장하거나 다른 뷰에 전달할 때 프로퍼티 래퍼를 사용한다.

이 상태를 현재 뷰가 직접 가지고 있는지, 부모 뷰에서 전달받는지, 아니면 별도의 객체가 관리하는지에 따라 사용하는 래퍼가 달라진다.

상위 뷰 → 하위 뷰

@State → @Binding

상위 뷰가 상태를 소유하고, 하위 뷰는 해당 상태를 수정할 수 있도록 @Binding으로 전달받는다.

뷰 모델 → 뷰 → 하위 뷰

ObservableObject 프로토콜을 채택한 뷰 모델에서는, 변경을 알려야 하는 값을 @Published 프로퍼티로 선언한다.(이 뷰 모델을 뷰에서 주입받아 사용할 때는 보통 @ObservedObject로 관찰함)

뷰에서 값을 읽어서 보여줄 때는 그냥 써도 됨(viewModel.프로퍼티). 그런데 하위 뷰가 그 값을 수정해야 한다면, 값 자체가 아니라 바인딩을 넘겨야 한다($viewModel.프로퍼티).

그러면 하위 뷰에선 @Binding으로 해당 프로퍼티를 받아서 사용한다.

@StateObject는? → 뷰모델 직접 생성할때 사용

생각해볼것

@State로 쓰기 vs. View model로 관리하기

검색해보니 표현의 문제는 @State로, 도메인적 문제는 View model에 넣으라고 한다.

  1. 단순 시트/알럿 토글, 액션시트, 포커스 상태, 임시 입력 드래프트와 같은 건 @State 로 관리하기
  2. 로그인 실패 후 “세션 만료” 알림과 같은 경우에는 View model로 관리하기

기준이 되게 자의적인 것 같음, 뭔가 기술적인 분류가 아니라. 팀 내부에서 정하는 문제.

어느 깊이까지 가야하는가. 고민해보기. 데이터가 어디까지 들어가는지…

추가. 멘토링 할 때 질문했는데, 지금 변경시킨 상태가 영속성이 있는지, 즉 DB에 들어갔다 나오는지를 판단해보라고 했다.

그런데 지금 적다보니 어디까지 DB에서 처리할지는 그것도 팀 나름 아닌가? 라는 생각이 좀 든다. 그런데 이렇게 하나하나 따지고 보면, 밑도 끝도 없으니까…

한 눈에 보기

속성용도언제 사용하는가소유 관계
@StateSwiftUI에서 뷰 내부의 상태 변화를 추적하고, 상태가 변경되면 뷰를 다시 렌더링하도록 한다.뷰 내부에서 상태를 정의할 때 (로컬 상태)상태 소유 (뷰가 상태를 소유)
@Binding부모 뷰에서 전달된 상태를 자식 뷰에서 사용하거나 수정할 수 있도록 연결할 때 사용된다.자식 뷰에서 상태를 전달받아 사용할 때상태 소유 X (다른 뷰에서 전달받음)
@StateObjectSwiftUI에서 객체를 처음 생성하고, 해당 객체의 상태를 뷰가 소유하며 관리할 때 사용한다.뷰 내부에서 상태 객체를 처음 생성할 때 (최초 소유)상태 소유 (뷰가 상태 객체를 소유)
@ObservedObject외부에서 상태를 관리하는 객체를 뷰에서 구독하고, 해당 객체의 상태 변화에 따라 뷰를 다시 렌더링한다.외부에서 관리되는 상태 객체를 뷰에서 사용할 때상태 소유 X (외부에서 관리)
@EnvironmentObject공유된 데이터 모델을 여러 뷰에서 사용할 수 있도록 전달할 때 사용된다. SwiftUI 환경에서 자동으로 주입된다.SwiftUI의 상위 뷰에서 공통으로 전달받은 객체를 하위 뷰에서 사용할 때상태 소유 X (환경에서 전달받음)
@EnvironmentSwiftUI에서 미리 정의된 환경 변수를 주입받아 사용할 때 사용된다.시스템 또는 부모 뷰에서 설정된 환경 값을 사용할 때상태 소유 X (환경에서 전달됨)
@PublishedObservableObject 프로토콜을 따르는 객체에서 특정 프로퍼티가 변경될 때 이를 자동으로 알림으로 보낸다.객체 내부에서 상태 변화를 알리고 싶을 때상태 소유 (객체가 상태를 소유)