Created
November 7, 2019 01:23
-
-
Save ainame/10b953bca71da39904309039bade2545 to your computer and use it in GitHub Desktop.
NSManagedObjectから任意のモデルに相互にマップしあう定義をプロトコル化するとCoreData Wrapper書くのに捗りそう
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import CoreData | |
protocol NSManagedObjectMappable: NSManagedObject where MapFrom.MapFrom == Self { | |
associatedtype MapFrom: MappableFromNSManagedObject | |
static func mappedObject(from object: MapFrom, in context: NSManagedObjectContext) -> Self | |
} | |
enum MappingError: Error { | |
case missingNonOptionalValue(String) | |
} | |
protocol MappableFromNSManagedObject where MapFrom.MapFrom == Self { | |
associatedtype MapFrom: NSManagedObjectMappable | |
static func mappedObject(from object: MapFrom) throws -> Self | |
} | |
extension MappableFromNSManagedObject { | |
static func mapValue<T>(from object: MapFrom, keyPath: KeyPath<MapFrom, T?>) throws -> T { | |
guard let value = object[keyPath: keyPath] else { | |
throw MappingError.missingNonOptionalValue(String(describing: keyPath)) | |
} | |
return value | |
} | |
} | |
struct Sample { | |
let string: String | |
let number: Int | |
let date: Date | |
} | |
extension Sample: MappableFromNSManagedObject { | |
static func mappedObject(from object: SampleRecord) throws -> Sample { | |
return Sample( | |
string: try mapValue(from: object, keyPath: \.string), | |
number: Int(object.number), | |
date: try mapValue(from: object, keyPath: \.date) | |
) | |
} | |
} | |
extension SampleRecord: NSManagedObjectMappable { | |
static func mappedObject(from object: Sample, in context: NSManagedObjectContext) -> Self { | |
let entity = Self.init(context: context) | |
entity.string = object.string | |
entity.number = Int32(object.number) | |
entity.date = object.date | |
return entity | |
} | |
} | |
class StoreService { | |
private let coreDataStack: CoreDataStack | |
init(from coreDataStack: CoreDataStack) { | |
self.coreDataStack = coreDataStack | |
} | |
func insert<T: MappableFromNSManagedObject>(_ object: T) throws { | |
let context = coreDataStack.newBackgroundContext | |
let entity = T.MapFrom.mappedObject(from: object, in: context) | |
try context.save() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment