CoreData ์ ์ฅ์๋ฅผ ์ถ๊ฐํ๋ ๋จ๊ณ๋ณ ๊ฐ์ด๋.
Xcode์์ Sources/CoreDataStorage/CoreDataStorage.xcdatamodeld ์ด๊ธฐ:
- ์ Entity ์ถ๊ฐ ๋๋ ๊ธฐ์กด Entity์ attribute ์ถ๊ฐ
UserCollectionEntity์ relationship ์ถ๊ฐ (ํ์ ์)
Lightweight migration์ด ์๋ ์ง์๋จ: ์์ฑ ์ถ๊ฐ, ์ต์ ๋ ๋ณ๊ฒฝ์ ์์ . ๊ด๊ณ ๋ณ๊ฒฝ/ํ์ ๋ณ๊ฒฝ์ ์ฃผ์ ํ์.
CoreDataStorage/XxxStorage/XxxStorage.swift:
import Foundation
import RxSwift
protocol XxxStorage {
func fetch() -> Single<[XxxModel]>
func update(_ item: XxxModel)
func reset()
}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)
}
}
}
}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)
// ...
)
}
}setUpUserCollection()์์ ๋ก๋ + update ๋ฉ์๋ ์ถ๊ฐ.
| Pattern | ์ค๋ช |
|---|---|
performBackgroundTask |
๋ชจ๋ ์ฐ๊ธฐ ์์ ์ ๋ฐฑ๊ทธ๋ผ์ด๋ context ์ฌ์ฉ |
getUserCollection |
UserCollectionEntity๊ฐ ๋ชจ๋ ์ปฌ๋ ์
์ ๋ฃจํธ |
context.saveContext() |
NSManagedObjectContext extension. hasChanges ์ฒดํฌ ํ ์ ์ฅ |
| Toggle | update()๋ ์กด์ฌํ๋ฉด ์ ๊ฑฐ, ์์ผ๋ฉด ์ถ๊ฐ (ํ ๊ธ ํจํด) |
Single<T> |
fetch๋ RxSwift Single๋ก ๋ฐํ |
| ์ญํ | 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