SwiftUI에서 Property Wrappers, Life Cycle에 대해서 알아봅시다
Life Cycle
onAppear
- onAppear은 View가 보여지기 전에 호출이 한 번만 호출이 되고 이후 뷰가 업데이트될 때는 호출되지 않음
- 사용 :
- 네트워크 요청, 데이터베이스 쿼리 등 뷰가 나타날 때 필요한 데이터를 가져오는 작업
- 애니메잇녀 시작, 타이머 설정 등 뷰가 화면에 나타날 때 시작되어야 하는 작업
- 뷰의 초기 상태 설정
onDisappear
- onDisappear은 뷰가 화면에서 사라질 때 호출되는 수정자고 뷰가 화면에서 완전히 사라질 때 호출이 됩니다
- onAppear에서 시작된 작업을 정리하고 리소스 해제뷰가 사라질 때 필요한 상태 변경 or 데이터를 저장합니다
task
- 뷰가 초기화될 때 비동기적으로 실행되는 작업입니다 onAppear과 유사하지만 뷰가 화면에 나타나기 전에 실행되는 것과는 다릅니다
- task는 취소가 가능하며 뷰가 사라지면 자동으로 취소됩니다
- 사용 :
- 뷰의 초기 상태를 설정하기 위해 필요한 비동기 데이터 가지고오기
- 뷰가 나타나기 전에 완료되어야 하는 백그라운드 작업 수행
프로퍼티 래퍼는 프로퍼티에 사용자 지정된 작업을 추가할 수 있는 기능입니다. 프로퍼티 접근 및 수정을 위해 재사용 가능한 로직을 정의하여 코드를 더 깔끔하고 유지 관리하기 쉽게 만들 수 있습니다.
기능 | SwiftUI | UIKit |
뷰의 생명 주기 관리 | onAppear, onDisappear, task 등의 수정자를 사용하여 뷰의 상태 변화에 따른 작업 처리 | viewDidLoad, viewWillAppear, viewDidAppear, viewWillDisappear, viewDidDisappear 등의 메서드를 오버라이드하여 뷰 컨트롤러의 생명 주기 관리 |
데이터 바인딩 | @State, @ObservedObject, @EnvironmentObject 등의 속성 래퍼를 사용하여 뷰와 데이터 모델 간의 자동 업데이트 지원 | Delegate 패턴, KVO, NotificationCenter 등을 사용하여 뷰와 데이터 모델 간의 수동 업데이트 처리 |
UI 업데이트 | 상태 변화에 따라 자동으로 UI 업데이트 | reloadData, setNeedsLayout, layoutIfNeeded 등의 메서드를 호출하여 수동으로 UI 업데이트 |
프로퍼티 래퍼 사용법:
프로퍼티 래퍼는 구조체, 클래스, 열거형과 함께 사용할 수 있습니다. 프로퍼티 래퍼의 init()은 본질적으로 비공개이므로 이를 사용하려면 프로퍼티 래퍼 구조체에 init()을 명시적으로 추가하여 래핑된 값이 필수이고 구조체 내에 정의되어 있는지 확인해야 합니다.
@State
- State 프로퍼티 래퍼를 사용하면 구조체 내부의 값을 수정할 수 있는데, 구조체는 값 유형이므로 일반적으로 허용되지 않습니다.
- SwiftUI에서 프로퍼티 앞에 @State를 사용하면 해당 프로퍼티의 저장소가 SwiftUI에서 관리하는 특별한 위치로 이동합니다. 이렇게 하면 SwiftUI가 보유 중이던 데이터를 잃지 않고 필요할 때마다 구조를 다시 생성할 수 있습니다.
- State 속성을 선언하지 않으면 해당 속성의 값을 변경할 수 없다는 뜻입니다.
State를 사용해야 하려면 다음과 같은 경우
@Binding
SwiftUI가 장려하는 것 중 하나는 앱에서 재사용 가능한 컴포넌트를 구축하는 것입니다. 하나의 뷰에 재사용 가능한 컴포넌트가 여러 개 있을 수 있습니다. 부모 보기에서 자식 보기의 변경 사항을 적용하려면 바인딩 속성 래퍼를 사용할 수 있습니다. 자식 보기에서 이를 사용하면 부모 보기의 소스를 읽거나 수정할 수 있습니다.
- 바인딩은 기본값을 허용하지 않습니다.
- 바인딩은 비공개가 아닌 공개여야 합니다.
- 바인딩 참조를 전달하려면 $를 사용해야 하는데 , $가 없으면 Swift는 바인딩 가능한 참조를 전달하는 대신 값의 복사본을 전달하기 때문입니다.
다음과 같은 경우에는 @Binding을 사용해야 합니다:
- 상위 뷰가 소유한 프로퍼티에 대한 읽기 및 쓰기 액세스 권한이 필요한 경우.
- 래핑된 속성이 값 유형(구조체 또는 열거형)입니다. (참조 유형(클래스)에도 @Binding을 사용할 수 있지만 그다지 일반적이지 않습니다.)
- 래핑된 속성을 소유하지 않습니다(상위 뷰에서 제공됨).
@Published
- Published는 SwiftUI에서 가장 유용한 프로퍼티 래퍼입니다. 이를 통해 변경 사항이 발생할 때 자동으로 알리는 관찰 가능한 객체를 사용할 수 있습니다.
- SwiftUI가 자동으로 변경 사항을 관찰하고 데이터에 의존하는 뷰의 본문 프로퍼티를 다시 호출합니다. Published로 표시된 개체 속성이 변경될 때마다 해당 개체를 사용하는 모든 뷰가 변경 사항을 반영하도록 다시 로드됩니다.
여기에서는 속성이 @Published로 표시되지 않습니다. 변경 알림은 전송되지 않습니다. 배열에 데이터를 자유롭게 추가할 수 있지만 뷰는 업데이트되지 않습니다.
@StateObject
스테이트 오브젝트는 @State 프로퍼티와 유사하지만, 관찰 가능한 오브젝트에 (ObservableObject)적용된다는 점이 다릅니다. 옵저버블 오브젝트(ObservableObject)프로토콜은 항상 참조 타입(클래스)이며, @Published 프로퍼티 중 하나가 변경될 때마다 SwiftUI에 알립니다.
- 뷰 중 하나에 참조 유형을 생성하고 해당 뷰 및 공유한 다른 뷰에서 사용할 수 있도록 유지해야 하는 경우 @StateObject가 사용됩니다.
- StateObject로 표시된 프로퍼티는 SwiftUI에서 구조체가 다시 생성되더라도 뷰가 필요한 한 처음에 할당된 인스턴스를 유지합니다.
- 이는 @State에서 볼 수 있는 것과 동일한 동작이지만, 구조체와 같은 값 유형이 아닌 ObservableObject에 적용된다는 점이 다릅니다.
ObservableObject는 anyObject에서 상속되기 때문에 클래스 프로토콜입니다.
다음과 같은 경우 @StateObject를 사용해야 합니다:
- 관찰 가능한 객체의 변경 또는 업데이트에 응답하려는 경우.
- StateObject를 사용하는 뷰는 ObservableObject 자체의 인스턴스를 만듭니다.
@ObservedObject
는 사용 중인 뷰에서 생성하거나 소유하지 않은 ObservableObject 인스턴스를 래핑하는 데 사용됩니다. StateObject 와 동일한 유형의 개체에 적용되며, 뷰가 자체 @ObservedObject 인스턴스를 만들지 않는다는 점을 제외하면 유사한 기능을 제공합니다.
우리가 작업해야 하는 세 가지 핵심 사항이 있습니다:
- ObservedObject로 표시된 모든 유형은 ObservableObject 프로토콜을 준수해야 합니다.
- 관찰된 개체는 뷰 외부에 있는 데이터를 위해 특별히 설계되었으므로 둘 이상의 뷰에서 공유될 수 있습니다. 관찰된 개체 속성 래퍼는 자동으로 속성을 면밀히 관찰하여 중요한 변경 사항이 있을 때 해당 속성을 사용하는 모든 뷰가 다시 로드되도록 합니다. 이는 또한 데이터가 다른 곳에서 생성된 다음 뷰로 전송되어야 함을 의미합니다.
- 관찰된 개체의 모든 속성이 뷰를 새로 고치는 것은 아님 - @Published 속성 래퍼는 변경 시 뷰를 업데이트해야 하는 관찰된 개체 내의 모든 속성에 추가됩니다.
관찰된 개체는 일반적으로 데이터가 뷰 외부에 저장될 때 사용되므로 뷰가 다시 그려져도 데이터가 손실되지 않습니다. StateObjects는 일반적으로 해당 데이터를 뷰 내부에 저장해야 하는 경우에 사용됩니다.
다음과 같은 경우 @ObservedObject를 사용해야 합니다:
- 관찰된 개체 의 변경 또는 업데이트에 응답하려는 경우.
- 뷰가 ObservedObject의 인스턴스 자체를 만들지 않습니다. (인스턴스를 생성하는 경우 @StateObject가 필요합니다.)
@EnvironmentObject
SwiftUI의 @EnvironmentObject 프로퍼티 래퍼를 사용하면 전체 SwiftUI 앱에서 공유 데이터에 의존하는 뷰를 만들 수 있습니다.
- 환경 오브젝트는 애플리케이션 수준에서 생성되고 저장됩니다. 모든 뷰가 원할 경우 읽고 쓸 수 있는 공유 데이터입니다.
- 모든 뷰가 동일한 모델을 가리키기 때문에 한 뷰에서 모델을 변경하면 모든 뷰가 즉시 업데이트되므로 앱의 다른 부분이 동기화되지 않을 위험이 없습니다.
- 환경 오브젝트 @환경 오브젝트는 관찰 가능한 오브젝트를 준수하는 클래스를 참조해야 하고, 여러 뷰에서 공유할 수 있으며, 중요한 변경 사항이 발생하면 관찰 중인 모든 뷰를 업데이트한다는 점에서 @ObservedObject와 공통점이 많습니다. 그러나 @환경 객체는 구체적으로 “이 객체가 현재 보기에서 생성되거나 특별히 전달되는 것이 아니라 외부 엔터티에서 제공될 것”이라는 의미입니다.
다음과 같은 경우 @EnvironmentObject를 사용해야 합니다:
- 일반적으로 @ObservedObject를 사용하지만 필요한 뷰에 도달하기 전에 여러 뷰의 이니셜라이저를 통해 ObservableObject를 전달해야 합니다.
@Environment
환경 속성 관찰자는 사용자 요구에 맞게 보기 또는 동작을 조정하기 위해 기기 설정 또는 기기 환경을 읽어야 할 때 사용됩니다. 이러한 값의 예로는 현재 디바이스 로캘, 디바이스 현재 달력, 색 구성표(어둡거나 밝음), 크기 클래스 등이 있습니다.
환경은 다음과 같은 경우에 사용해야 합니다:
- 키를 사용하여 SwiftUI 환경에 일부 값을 삽입하려는 경우.
- 삽입된 프로퍼티는 @EnvironmentObject 처럼 동작할 필요는 없습니다.
- .environment 수정자를 받은 뷰의 하위 뷰인 모든 뷰에서 속성을 사용할 수 있어야 합니다.
AppStorage
AppStorage 속성 래퍼는 UserDefaults 를 둘러싼 앱 전체 래퍼입니다. 즉, 간단한 키/값 쌍을 저장하는 데 유용합니다. UserDefaults의 데이터가 변경되면 뷰가 다시 로드됩니다. 프로퍼티에 값을 할당하여 @AppStorage의 값을 업데이트할 수 있습니다.
언제 @AppStorage를 사용해야 합니다:
- 간단한 사용자 환경 설정을 저장하는 경우.
- 사용자가 앱을 마지막으로 실행한 시간과 같은 간단한 데이터를 추적하려고 합니다.
- 앱 재시작 시 서비스를 제공해야 하는 매우 간단한 상태를 유지해야 합니다.
@SceneStorage
SceneStorage 속성 래퍼는 @AppStorage와 유사하지만 뷰가 현재 있는 장면에 로컬로 데이터를 유지한다는 점만 다릅니다. iOS에서는 일반적으로 앱에 하나의 씬이 있지만 Mac 및 iPad에서는 앱에 여러 개의 씬이 있을 수 있습니다. 장면이 일시적으로 제거되었다가 나중에 복원되면 장면 저장소를 다시 사용할 수 있습니다. 장면이 삭제되면 모든 장면 관련 데이터도 함께 삭제됩니다.
앱에 필수적이지 않은 상태 관련 데이터에만 장면 저장소를 사용해야 합니다.
@SceneStorage는 다음과 같은 경우에 사용해야 합니다:
- 현재 씬과 관련된 간단한 상태를 저장하는 경우
- 유지하려는 데이터가 민감하거나 업무상 중요하지 않은 경우 .
참조
https://developer.apple.com/documentation/swiftui/view
'SwiftUI' 카테고리의 다른 글
SwiftUI | Final Project _ 3일차 (1) | 2024.09.24 |
---|---|
SwiftUI | HeaderView(Sticky View)만들기전 알아야할 기본 상식 정의 + 만들기 - 1 (0) | 2024.09.19 |
SwiftUI | 프로젝트에서 info.plist가 누락되었을 때 (0) | 2024.08.22 |
SwiftUI | 회원가입 만들기 (0) | 2024.08.22 |
SwiftUI | SwiftData Tutorials - List / NavigationStack / DatePicker (0) | 2024.08.08 |