본문 바로가기
Ios/Swift UI

@Observable, @ObservedObject 를 알아봅시다

by 잘먹는 개발자 에단 2024. 7. 19.

@Observable

1. Swift 5.7에서 새롭게 도입된 속성 래퍼입니다.

2. Swift의 새로운 Concurrency 모델과 함께 사용됩니다.

3. 클래스를 관찰 가능하게 만들며, 상태 변화를 감지하고 UI업데이트를 자동으로 처리합니다.

4. SwiftUI에 기존에 @ObservedObject와 @StateObject가 있었는데 그에 대한 대안으로 만들어졌습니다.

5. 최신 Swift에서 도입된만큼 최신 Swift버전에서만 사용가능합니다. 

 

다음은 @ObservedObject입니다.

 

@ObservedObject

1. @ObservedObject는 SwiftUI에서 사용할 수 있는 프로퍼티 래퍼입니다. 

2. 상태변화를 관찰할 객체를 지정합니다.

3. @ObservedObject는 ObservableObject 프로토콜을 채택(준수)하는 객체에 적용됩니다.

4. ObservableObject는 클래스에 적용되며, 클래스 내부의 프로퍼티가 변경될 때 이를 구독하는 모든 뷰에 변경사항을 알립니다.

5. @ObservedObject를 사용하면 뷰는 해당 객체의 상태가 변경될 때마다 업데이트 됩니다. 

 

다음은 예제입니다.

import SwiftUI

@Observable
class Landmark {
    var name: String
    var isFavorite: Bool

    init(name: String, isFavorite: Bool) {
        self.name = name
        self.isFavorite = isFavorite
    }
}

struct LandmarkDetail: View {
    @ObservedObject var landmark: Landmark

    var body: some View {
        VStack {
            Text(landmark.name)
            Toggle(isOn: $landmark.isFavorite) {
                Text("Favorite")
            }
        }
    }
}

 

 

 

마치 리액트의 상태와 비슷한 것 같아요.

 

 

 

 

보통 Swift UI에서 많이 쓰인다는데 Swift Tutorial 3에 나오네요.

( https://developer.apple.com/tutorials/swiftui/handling-user-input )

 

import Foundation


@Observable
class ModelData {
    var landmarks: [Landmark] = load("landmarkData.json")
}


func load<T: Decodable>(_ filename: String) -> T {
    let data: Data


    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }


    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }


    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}