Я пишу универсальный класс-обертку для основных данных.
Вот некоторые из моих основных типов.Ничего особенного.
typealias CoreDataSuccessLoad = (_: NSManagedObject) -> Void
typealias CoreDataFailureLoad = (_: CoreDataResponseError?) -> Void
typealias ID = String
enum CoreDataResult<Value> {
case success(Value)
case failure(Error)
}
enum CoreDataResponseError : Error {
typealias Minute = Int
typealias Key = String
case idDoesNotExist
case keyDoesNotExist(key: Key)
case fetch(entityName: String)
}
Я абстрагировал свои записи coredata в протоколе.Буду признателен, если вы дадите мне знать о ваших комментариях об абстракции, которую я пытаюсь осуществить.Тем не менее, в расширении я сталкиваюсь со следующей ошибкой:
Невозможно преобразовать значение типа 'NSFetchRequest' в ожидаемый тип аргумента 'NSFetchRequest <_>'
Не совсем точнокак я могу это исправить.Я пробовал варианты изменения моего кода, но не нашел успеха ...
protocol CoreDataWriteManagerProtocol {
associatedtype ManagedObject : NSManagedObject
var persistentContainer : NSPersistentContainer {get}
var idName : String {get}
func loadFromDB(storableClass : ManagedObject.Type, id: ID) throws -> CoreDataResult<ManagedObject>
func update(storableClass : ManagedObject.Type, id: ID, fields: [String : Any]) throws
func fetch(request: NSFetchRequest<ManagedObject>, from context: NSManagedObjectContext)
init(persistentContainer : NSPersistentContainer)
}
extension CoreDataWriteManagerProtocol {
private func loadFromDB(storableClass : ManagedObject.Type, id: ID) -> CoreDataResult<ManagedObject>{
let predicate = NSPredicate(format: "%@ == %@", idName, id)
let fetchRequest : NSFetchRequest = storableClass.fetchRequest()
fetchRequest.predicate = predicate
// ERROR at below line!
return fetch(request: fetchRequest, from: persistentContainer.viewContext)
}
func fetch<ManagedObject: NSManagedObject>(request: NSFetchRequest<ManagedObject>, from context: NSManagedObjectContext) -> CoreDataResult<ManagedObject>{
guard let results = try? context.fetch(request) else {
return .failure(CoreDataResponseError.fetch(entityName: request.entityName ?? "Empty Entity Name")) // @TODO not sure if entityName gets passed or not.
}
if let result = results.first {
return .success(result)
}else{
return .failure(CoreDataResponseError.idDoesNotExist)
}
}
}
Дополнительно, если я изменил строку:
let fetchRequest : NSFetchRequest = storableClass.fetchRequest()
на:
let fetchRequest : NSFetchRequest<storableClass> = storableClass.fetchRequest()
Я получаю следующую ошибку:
Использование необъявленного типа 'storableClass'`
Моя интуиция говорит мне, что компилятор не может отобразить "параметры, которыеявляются типами 'т.е. он не понимает, что storableClass
на самом деле является типом.Вместо этого он может отображать только общие параметры или фактические типы.Следовательно, это не работает.
РЕДАКТИРОВАТЬ:
Я использовал статический подход Vadian и написал это:
private func create(_ entityName: String, json : [String : Any]) throws -> ManagedObject {
guard let entityDescription = NSEntityDescription.entity(forEntityName: entityName, in: Self.persistentContainer.viewContext) else {
print("entityName: \(entityName) doesn't exist!")
throw CoreDataError.entityNotDeclared(name: entityName)
}
let _ = entityDescription.relationships(forDestination: NSEntityDescription.entity(forEntityName: "CountryEntity", in: Self.persistentContainer.viewContext)!)
let relationshipsByName = entityDescription.relationshipsByName
let propertiesByName = entityDescription.propertiesByName
guard let managedObj = NSEntityDescription.insertNewObject(forEntityName: entityName, into: Self.persistentContainer.viewContext) as? ManagedObject else {
throw CoreDataError.entityNotDeclared(name: entityName)
}
for (propertyName,_) in propertiesByName {
if let value = json[propertyName] {
managedObj.setValue(value, forKey: propertyName)
}
}
// set all the relationships
guard !relationshipsByName.isEmpty else {
return managedObj
}
for (relationshipName, _ ) in relationshipsByName {
if let object = json[relationshipName], let objectDict = object as? [String : Any] {
let entity = try create(relationshipName, json: objectDict)
managedObj.setValue(entity, forKey: relationshipName)
}
}
return managedObj
}
Но следующий фрагмент не является общим, как в IКастую с as? ManagedObject
.По сути, это не Swifty, как говорит Вадиан:
guard let managedObj = NSEntityDescription.insertNewObject(forEntityName: entityName, into: Self.persistentContainer.viewContext) as? ManagedObject else {
throw CoreDataError.entityNotDeclared(name: entityName)
}
Есть ли способ обойти это?