내가 iOS 개-발자라니.

옆집 스위프트: WWDC 24 SwiftData 커스텀 데이터 저장소 예제 본문

This is da(大) SWIFT

옆집 스위프트: WWDC 24 SwiftData 커스텀 데이터 저장소 예제

옆집개 2024. 6. 26. 17:42

SwiftData 커스텀 데이터 저장소 예제

 

1. DataStore의 역할

- 데이터 저장 및 읽기: SwiftData에서 DataStore는 데이터의 영속성을 담당하며, 모델 컨텍스트(ModelContext)와 모델 컨테이너(ModelContainer)와 상호작용한다.

- 데이터 스냅샷: DataStore는 모델의 현재 상태를 캡처한 스냅샷을 사용하여 데이터를 읽고 씀.

 

2. DataStore 프로토콜

- DataStoreConfiguration: 저장소의 설정을 정의

- DataStoreSnapshot: 모델 값과 상호작용하는 스냅샷을 정의

- DataStore: 저장소 구현을 정의하며, 페칭(fetch) 및 저장(save) 기능을 포함

 

3. 커스텀 JSON 저장소 구현 예제

- JSONStoreConfiguration: JSON 파일을 사용하는 커스텀 저장소 설정을 정의

- JSONStore: DataStore 프로토콜을 구현하여 JSON 파일에 데이터를 저장하고 읽음

  - fetch 메소드: JSON 파일에서 데이터를 읽고, 스냅샷을 반환

  - save 메소드: 데이터를 JSON 파일에 저장합니다. 삽입, 업데이트, 삭제 작업을 처리

 

struct JSONStoreConfiguration: DataStoreConfiguration {
    typealias Store = JSONStore
    var fileURL: URL
}
 
class JSONStore: DataStore {
    typealias Configuration = JSONStoreConfiguration
    typealias Snapshot = DefaultSnapshot
 
    let configuration: Configuration
 
    init(configuration: Configuration) {
        self.configuration = configuration
    }
 
    func fetch(_ request: DataStoreFetchRequest) throws -> DataStoreFetchResult<Snapshot> {
        let data = try Data(contentsOf: configuration.fileURL)
        let snapshots = try JSONDecoder().decode([Snapshot].self, from: data)
        return DataStoreFetchResult(snapshots: snapshots)
    }
 
    func save(_ request: DataStoreSaveChangesRequest<Snapshot>) throws -> DataStoreSaveChangesResult<Snapshot> {
        var snapshotsByIdentifier = try read()
       
        // Process inserts
        for snapshot in request.inserts {
            let identifier = UUID().uuidString
            snapshotsByIdentifier[identifier] = snapshot
        }
       
        // Process updates
        for snapshot in request.updates {
            snapshotsByIdentifier[snapshot.identifier] = snapshot
        }
       
        // Process deletes
        for snapshot in request.deletes {
            snapshotsByIdentifier.removeValue(forKey: snapshot.identifier)
        }
       
        let data = try JSONEncoder().encode(Array(snapshotsByIdentifier.values))
        try data.write(to: configuration.fileURL)
       
        return DataStoreSaveChangesResult(remappedIdentifiers: [:])
    }
    
    private func read() throws -> [String: Snapshot] {
        let data = try Data(contentsOf: configuration.fileURL)
        let snapshots = try JSONDecoder().decode([Snapshot].self, from: data)
        return Dictionary(uniqueKeysWithValues: snapshots.map { ($0.identifier, $0) })
    }
}