Skip to content

Latest commit

ย 

History

History
142 lines (113 loc) ยท 4.3 KB

File metadata and controls

142 lines (113 loc) ยท 4.3 KB

Add a CoreData Entity

CoreData ์ €์žฅ์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ๊ฐ€์ด๋“œ.

Steps

1. CoreData Model ์ˆ˜์ •

Xcode์—์„œ Sources/CoreDataStorage/CoreDataStorage.xcdatamodeld ์—ด๊ธฐ:

  • ์ƒˆ Entity ์ถ”๊ฐ€ ๋˜๋Š” ๊ธฐ์กด Entity์— attribute ์ถ”๊ฐ€
  • UserCollectionEntity์— relationship ์ถ”๊ฐ€ (ํ•„์š” ์‹œ)

Lightweight migration์ด ์ž๋™ ์ง€์›๋จ: ์†์„ฑ ์ถ”๊ฐ€, ์˜ต์…”๋„ ๋ณ€๊ฒฝ์€ ์•ˆ์ „. ๊ด€๊ณ„ ๋ณ€๊ฒฝ/ํƒ€์ž… ๋ณ€๊ฒฝ์€ ์ฃผ์˜ ํ•„์š”.

2. Storage ํ”„๋กœํ† ์ฝœ ์ •์˜

CoreDataStorage/XxxStorage/XxxStorage.swift:

import Foundation
import RxSwift

protocol XxxStorage {
    func fetch() -> Single<[XxxModel]>
    func update(_ item: XxxModel)
    func reset()
}

3. CoreData ๊ตฌํ˜„์ฒด

CoreDataStorage/XxxStorage/CoreDataXxxStorage.swift:

import Foundation
import RxSwift

final class CoreDataXxxStorage: XxxStorage {
    private let coreDataStorage: CoreDataStorage

    init(coreDataStorage: CoreDataStorage = CoreDataStorage.shared) {
        self.coreDataStorage = coreDataStorage
    }

    func fetch() -> Single<[XxxModel]> {
        return Single.create { single in
            self.coreDataStorage.performBackgroundTask { context in
                do {
                    let object = try self.coreDataStorage.getUserCollection(context)
                    // Entity์—์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
                    let entities = object.xxx?.allObjects as? [XxxEntity] ?? []
                    let models = try entities.map { try $0.toDomain() }
                    single(.success(models))
                } catch {
                    single(.failure(CoreDataStorageError.readError(error)))
                }
            }
            return Disposables.create()
        }
    }

    func update(_ item: XxxModel) {
        coreDataStorage.performBackgroundTask { context in
            do {
                let object = try self.coreDataStorage.getUserCollection(context)
                // ํ† ๊ธ€ ํŒจํ„ด: ์žˆ์œผ๋ฉด ์ œ๊ฑฐ, ์—†์œผ๋ฉด ์ถ”๊ฐ€
                let items = object.xxx?.allObjects as? [XxxEntity] ?? []
                if let index = items.firstIndex(where: { $0.id == item.id }) {
                    object.removeFromXxx(items[index])
                } else {
                    let newItem = XxxEntity(item, context: context)
                    object.addToXxx(newItem)
                }
                context.saveContext()
            } catch {
                debugPrint(error)
            }
        }
    }
}

4. Entity Mapping

CoreDataStorage/XxxStorage/EntityMapping/XxxEntity+Mapping.swift:

import Foundation
import CoreData

extension XxxEntity {
    // Domain โ†’ Entity
    convenience init(_ model: XxxModel, context: NSManagedObjectContext) {
        self.init(context: context)
        self.name = model.name
        self.value = Int64(model.value)
        // ...
    }

    // Entity โ†’ Domain
    func toDomain() throws -> XxxModel {
        guard let name = self.name else {
            throw CoreDataStorageError.notFound
        }
        return XxxModel(
            name: name,
            value: Int(self.value)
            // ...
        )
    }
}

5. Items.swift์— ์—ฐ๊ฒฐ (ํ•„์š” ์‹œ)

setUpUserCollection()์—์„œ ๋กœ๋“œ + update ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€.

Key Patterns

Pattern ์„ค๋ช…
performBackgroundTask ๋ชจ๋“  ์“ฐ๊ธฐ ์ž‘์—…์€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ context ์‚ฌ์šฉ
getUserCollection UserCollectionEntity๊ฐ€ ๋ชจ๋“  ์ปฌ๋ ‰์…˜์˜ ๋ฃจํŠธ
context.saveContext() NSManagedObjectContext extension. hasChanges ์ฒดํฌ ํ›„ ์ €์žฅ
Toggle update()๋Š” ์กด์žฌํ•˜๋ฉด ์ œ๊ฑฐ, ์—†์œผ๋ฉด ์ถ”๊ฐ€ (ํ† ๊ธ€ ํŒจํ„ด)
Single<T> fetch๋Š” RxSwift Single๋กœ ๋ฐ˜ํ™˜

Reference Files

์—ญํ•  File
CoreData ์‹ฑ๊ธ€ํ†ค CoreDataStorage/CoreDataStorage.swift
Storage ํ”„๋กœํ† ์ฝœ ์˜ˆ์‹œ CoreDataStorage/ItemsStorage/ItemsStorage.swift
๊ตฌํ˜„์ฒด ์˜ˆ์‹œ CoreDataStorage/ItemsStorage/CoreDataItemsStorage.swift
Entity ๋งคํ•‘ ์˜ˆ์‹œ CoreDataStorage/ItemsStorage/EntityMapping/ItemEntity+Mapping.swift
Data Model CoreDataStorage/CoreDataStorage.xcdatamodeld

์ฃผ์˜์‚ฌํ•ญ

  • NSPersistentCloudKitContainer ์‚ฌ์šฉ ์ค‘ โ†’ gotchas.md #8
  • Merge policy: NSMergeByPropertyObjectTrumpMergePolicy
  • viewContext.automaticallyMergesChangesFromParent = true