Swift - 뷰간 데이터 공유(Sharing data between views)

Andrew·2022년 9월 23일
0

Swift Playgrounds 앱을 통해 공부한 내용 정리

ObservableObject

어떤 View가 쳐다볼(observe) 클래스 객체로, 클래스 안에 @Published 상태를 달아 뷰가 쳐다볼 데이터를 정의할 수 있다.

import SwiftUI


class CreatureZoo : ObservableObject {
    @Published var creatures = [
            Creature(name: "Gorilla", emoji: "🦍"),
            Creature(name: "Peacock", emoji: "🦚"),
            Creature(name: "Squid", emoji: "🦑"),
            Creature(name: "T-Rex", emoji: "🦖"),
            Creature(name: "Dog", emoji: "🐶"),
            Creature(name: "Cat", emoji: "🐈"),
            Creature(name: "Eagle", emoji: "🦅"),
        ]
}

struct Creature : Identifiable {
    var name : String
    var emoji : String
    
    var id = UUID()
    var offset = CGSize.zero
    var rotation : Angle = Angle(degrees: 0)
}
...

StateObject

뷰가 쳐다볼 StateObject를 생성한다. 이 객체 내의 @Published 데이터가 수정되면, 쳐다보고 있던 뷰(observer)는 바뀐 뷰를 렌더링하게 된다.

import SwiftUI
import Guide

@main
struct MyApp: App {
    @StateObject var data = CreatureZoo()  // state object 생성
    
    var body: some Scene {
        SPCAssessableWindowGroup(app: self, assessmentCandidates: [CreatureZoo()]) {
            NavigationView { 
                ContentView()
                    .navigationTitle("My Creatures")
            }
            .environmentObject(data)
        }
    }
}

View Hierarchy

메인 뷰인 MyApp에서 어떤 state object를 쳐다보고 있을 때, MyApp에 추가되는 다른 view에서도 해당 state object의 상태를 계속 쳐다보게 되는 구조이다. 트리와 같은 구조로 생각하면 된다.

MyApp (@StateObject)
|
|
ContentView (@EnviromentObject)
|
|
...

EnvironmentObject

View hierarchy를 타고 내려와 메인 뷰에서 생성한 state object를 하위 뷰에서 쳐다보고 싶을 때, 하위 뷰에서 또 다시 새로 state object를 생성하는 것이 아닌, environment object를 선언함으로써 메인 뷰에서 생성한 state object를 그대로 지켜볼 수 있다.

import SwiftUI
import Guide

struct ContentView: View {
    @EnvironmentObject var data : CreatureZoo

    var body: some View {
        SPCAssessableGroup(view: self) {
            List {
                Text("ContentView")
                
                Section("Dance") {
                    NavigationLink("Make the Creatures Dance") {
                        DancingCreatures()
                            .navigationTitle("Dancing Creatures")
                    }
                }
                ForEach(data.creatures) { creature in    
                	CreatureRow(creature: creature)
                }                   
            }
        }
    }
}

profile
조금씩 나아지는 중입니다!

0개의 댓글