SwiftUI

SwiftUI | Property Wrappers + Life Cycle

ziziDev 2024. 9. 29. 15:52
반응형

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

 

View | Apple Developer Documentation

A type that represents part of your app’s user interface and provides modifiers that you use to configure views.

developer.apple.com

 

 

Property Wrappers in Swift UI

Deciding when to use each of SwiftUI’s key property wrappers..😎

medium.com

 

 

반응형