SwiftUI / Monitoring data changes in your app

Minsang Kang·2023년 10월 28일
0

SwiftUI

목록 보기
12/12

이전 글에서 SwiftUI / @StateObject, @ObservedObject, @EnvironmentObject 내용을 살펴보면서 Data Model을 사용하기 위한 내용을 살펴봤습니다.

이번 글을 통해 앞선 다양한 프로퍼티래퍼를 사용하여 SwiftUI 에서 iOS16 기준으로 ViewData Model을 사용하여 앱을 구현하는 내용을 살펴보겠습니다.

Apple Developer 문서에 표현된 Monitoring data changes in your app 탐방
https://developer.apple.com/documentation/swiftui/monitoring-model-data-changes-in-your-app

Make model data observable

  • ObsevableObject 프로토콜을 채택하여 model을 만드세요
  • 변경가능해야하며 변경사항에 따른 UI표시가 필요한 속성들만 @Published 값으로 설정하세요
  • 그 외의 경우는 @Published가 아닌 속성들을 지니세요
class Book: ObservableObject {
    @Published var title = "Sample Book Title"

    let identifier = UUID() // A unique identifier that never changes.
}

Monitor changes in observable objects

  • @ObservedObject 프로퍼티래퍼를 통해 model의 변경사항을 SwiftUI가 인지할 수 있습니다.
  • @ObservedObject 프로퍼티래퍼를 통해 하위 view로 전달이 가능합니다.
struct BookView: View {
    @ObservedObject var book: Book
    
    var body: some View {
        BookEditView(book: book)
    }
}

struct BookEditView: View {
    @ObservedObject var book: Book

    // ...
}

Instantiate a model object in a view

  • @StateObject 프로퍼티래퍼는 @ObservedObject 프로퍼티래퍼와 동일한 역할을 제공하며, model을 single source of truth 형태로 안전하게 지닐 수 있습니다.
  • SwiftUI로 인해 View가 재생성되는 것과 상관없이 단일 인스턴스를 지닐 수 있습니다.
  • 이러한 @StateObject 값을 하위 view로 @ObservedObject로 전달할 수 있습니다.
struct LibraryView: View {
    @StateObject private var book = Book()
    
    var body: some View {
        BookView(book: book)
    }
}
  • App, Scene 내에서도 동일하게 @StateObject를 선언할 수 있습니다.
@main
struct BookReader: App {
    @StateObject private var library = Library()

    // ...
}

Share an object throughout your app

  • .environmentObject 모디파이어를 통해 App, 또는 모든 하위 view에서 접근가능한 model을 environment로 설정할 수 있습니다.
  • 이를 통해 여러 view 계층을 통해 전달하지 않아도 environment를 통해 공유할 수 있습니다.
@main
struct BookReader: App {
    @StateObject private var library = Library()
    
    var body: some Scene {
        WindowGroup {
            LibraryView()
                .environmentObject(library)
        }
    }
}
  • @EnvironmentObject 프로퍼티래퍼를 선언하여 하위 view에서 접근가능합니다.
struct LibraryView: View {
    @EnvironmentObject var library: Library
    
    // ...
}
  • PreviewProvider 내에서도 동일하게 environment를 설정함니다.
struct LibraryView_Previews: PreviewProvider {
    static var previews: some View {
        LibraryView()
            .environmentObject(Library())
    }
}

Create a two-way connection using bindings

  • UI 내에서 model의 데이터를 변경하고자 하는 경우 read/write가 가능한 양방향 binding을 사용하세요.
  • @StateObject, 또는 @ObservedObject로 지닌 model명 앞에 $를 붙여 binding을 사용할 수 있습니다.
  • $book.title 을 통해 TextField로 입력된 값을 @Published 값인 title로 반영할 수 있습니다.
struct BookEditView: View {
    @ObservedObject var book: Book
    
    var body: some View {
        TextField("Title", text: $book.title)
    }
}

iOS17: Observable

추가로 iOS17 이상의 경우 애플이 새롭게 소개하는 @Observable 프로퍼티래퍼를 사용한 Managing model data in your app 내용을 참고하면 되겠습니다.

그리고 위 내용을 토대로 작성된 경우 Migrating from the Observable Object protocol to the Observable macro 내용을 참고하여 @Observable 프로퍼티래퍼를 사용한 형식으로 변경하면 되겠습니다!

profile
 iOS Developer

0개의 댓글