iOS

[iOS] Linking Data Between Two Core Data Stores / 두 코어데이터 저장소 사이에 데이터 연결하기

Kim_Baechu 2022. 10. 24. 17:00

Linking Data Between Two Core Data Stores

https://developer.apple.com/documentation/coredata/linking_data_between_two_core_data_stores

두 개의 서로 다른 저장소에 데이터를 구성하고 이들 사이에 링크를 구현합니다.

Overview

때로는 앱이 여러 개의 Core Data 저장소와 함께 작동해야 합니다.

예를 들어, 읽기 전용 저장소의 데이터에 레이블을 지정해야 하는 경우 레이블링 결과를 다른 저장소에 기록해야 합니다.

큰 데이터 세트의 일부를 iCloud에 동기화해야 하는 경우, 앱이 두 개의 스토어에 데이터를 구성하여 하나는 CloudKit에 미러링하고 다른 하나는 로컬 장치에 보관할 수 있습니다.

이 샘플 앱에서는 하나의 Core Data 스택으로 두 개의 서로 다른 스토어에서 데이터를 관리하고 연결하는 방법을 보여 줍니다.

그 앱은 책의 기록과 책에 대한 사용자 피드백을 두 개의 분리된 저장소로 정리합니다.

그것은 앱에서 책의 피드백에 직접 액세스할 수 있는 fetched(가져온) 프로퍼티로 상점의 두 엔티티를 연결합니다.

사용자가 피드백 레코드를 추가하거나 제거하고 변경 내용을 저장하면 앱은 북 오브젝트를 새로 고쳐 fetched(가져온) 프로퍼티를 업데이트합니다.

Configure the Data Model

샘플 앱은 Core Data 모델에 Book 엔티티와 Feedback 엔티티를 만든 다음 각 스토어에 대해 Book Feedback이라는 각각의 저장소를 위한 Configuration(구성)을 생성하여 스토어의 엔티티를 포함합니다.

엔티티를 연결하기 위해 샘플 앱은 fetched(가져온) 프로퍼티인 feedbackList을 북 엔티티에 추가합니다. 이 프로퍼티는 엔티티의 Xcode에서 Fetched Properties 섹션에 표시됩니다.

fetched(가져온) 프로퍼티의 대상이 Feedback 엔티티로 설정되고 해당 predicate는 bookUUID == $FETCH_SOURCE.uuid 입니다.

여기서 bookUUID는 대상의 key path이며 $FETCH_SOURCE는 fetched(가져온) 프로퍼티의 소스(이 예제에서는 Book 오브젝트)로 바뀝니다.

이 설정을 통해 앱이 Book 오브젝트를 새로 고치고 해당 feedbackList 프로퍼티에 액세스할 때 Core Data는 Feedback 엔티티에 predicate를 사용하여 NSFetchRequest를 실행하고 결과를 프로퍼티에 반환합니다.

Set Up the Core Data Stack

샘플 앱은 스토어의 URL 및 모델 구성을 사용하여 각 스토어에 대해 하나의 NSPersistentStoreDescription 오브젝트를 생성한 다음 NSPersistentContainer를 사용하여 스토어를 로드합니다.

let container = NSPersistentContainer(name: "CoreDataFetchedProperty")
let defaultDirectoryURL = NSPersistentContainer.defaultDirectoryURL()

let bookStoreURL = defaultDirectoryURL.appendingPathComponent("Books.sqlite")
let bookStoreDescription = NSPersistentStoreDescription(url: bookStoreURL)
bookStoreDescription.configuration = "Book"

let feedbackStoreURL = defaultDirectoryURL.appendingPathComponent("Feedback.sqlite")
let feedbackStoreDescription = NSPersistentStoreDescription(url: feedbackStoreURL)
feedbackStoreDescription.configuration = "Feedback"

container.persistentStoreDescriptions = [bookStoreDescription, feedbackStoreDescription]
container.loadPersistentStores(completionHandler: { (_, error) in
    guard let error = error as NSError? else { return }
    fatalError("###\\(#function): Failed to load persistent stores:\\(error)")
})

이 설정을 통해 앱이 데이터를 가져오거나 변경하면 Core Data는 엔티티가 있는 위치를 기준으로 요청을 올바른 저장소로 자동으로 라우팅합니다.

Implement the Fetched Property

Xcode는 현재 fetched(가져온) 프로퍼티에 대한 코드를 생성하지 않으므로 샘플 앱은 다음 extension를 추가하여 feedbackList에 대한 접근자를 제공합니다.

extension Book {
    var feedbackList: [Feedback]? { // The accessor of the feedbackList property.
        return value(forKey: "feedbackList") as? [Feedback]
    }
}

feedbackList 접근자를 사용하여 앱은 fetched(가져온) 프로퍼티에 직접 액세스할 수 있습니다.

guard let feedback = book.feedbackList?[indexPath.row] else { return cell }
let rating = Int(feedback.rating)
let comment = feedback.comment ?? ""

관계(relationship)와 달리 fetched(가져온) 프로퍼티는 NSFetchRequest의 predicate에 사용할 수 없습니다.

관리되는 컨텍스트가 저장될 때도 자동으로 업데이트되지 않습니다.

샘플 앱이 Feedback 엔티티에 변경 사항을 저장할 때, 앱은 book.feedbackList 프로퍼티를 업데이트하기 위해 책 오브젝트를 새로고침 해야합니다.