[SwiftUI] iOS17 이후의 상태 관리

이상현·2024년 6월 7일
0

Swift

목록 보기
7/10
post-thumbnail

WWDC23 이후 완전히 개편된 데이터 상태 관리에 대한 방법입니다.

iOS 17 이후 Observation 프레임워크의 @Observable Macro를 사용하여 SwiftUI의 데이터 흐름을 다룰 수 있게 되었다.

@Observable 매크로

ObservavleObject 프로토콜을 채택하는 대신에,
상태 관리할 클래스 또는 구조체 위에 @Observable 매크로를 표시한다.

@Observable
class Library {
    var books: [Book] = [Book(), Book(), Book()]
}

이전처럼 내부 프로퍼티에 추가로 프로퍼티 래퍼 @Published 를 사용할 필요 없다.

대신, 속성을 상태 관리에서 제거하려면 속성에 @ObservationIgnored 매크로를 사용하면 된다.

SwiftUI 는 observable 한 속성들이 업데이트 되고, 뷰의 body 가 그 속성을 바로 읽을때만 뷰를 업데이트 한다.

body 에게 읽하지 않는 변수가 변경될때는 뷰를 업데이트 하지 않는다.

마찬가지로, 모델을 클래스로 사용하고 있다면 ObservableObject 프로토콜을 채택하고 @Published 프로퍼티 래퍼를 사용했을것이다. 그것을 없애고 @Observable 매크로만 작성해주자.

-> 이 경우에 뷰에서 해당 모델을 사용할 때 @State 조차 붙혀주지 않아도 된다. @Observable 매크로를 작성한 클래스는 내부 속성의 변화를 알아서 감지해서 body 를 업데이트 한다.

@State 프로퍼티 래퍼

ObservavleObject 를 사용한 객체에는 @StateObject 를 적어줬어야 하는데,

이제는 @Observable 을 사용한 참조 타입은 값 타입과 마찬가지로, @State 를 적어주면 된다.

@Environment 프로퍼티 래퍼

다음 앱 구조는 Library 인스턴스를 만들고, StateObject 로 저장한 후 .environmentObject 로 환경 값으로 넣어줬다.

// BEFORE
@main
struct BookReaderApp: App {
    @StateObject private var library = Library()


    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environmentObject(library)
        }
    }
}

// AFTER
@main
struct BookReaderApp: App {
    @State private var library = Library()


    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environment(library)
        }
    }
}

@Observable 을 사용했으면 @State 로 선언하고 .environment 로 넣어주면 된다.

그리고 LibraryView 안에서는 다음과 같이 사용한다.

// BEFORE
struct LibraryView: View {
    @EnvironmentObject var library: Library


    var body: some View {
        List(library.books) { book in
            BookView(book: book)
        }
    }
}

// AFTER
struct LibraryView: View {
    @Environment(Library.self) private var library
    
    var body: some View {
        List(library.books) { book in
            BookView(book: book)
        }
    }
}

@Bindable 프로퍼티 래퍼

단, Observable 타입의 뷰가 바인딩이 필요해지면, @ObservedObject 을 지우고, @Bindable 프로퍼티 래퍼를 작성한다.

@Bindable@Observable 을 사용한 클래스의 프로퍼티에 대한 바인딩을 생성할 수 있도록 한다.

0개의 댓글