Мне нравятся идеи , представленные в этом посте , о создании независимого от базы данных, ориентированного на протокол кода.
Так, скажем, у меня есть протокол, такой как:
protocol Database {
func loadObjects<T>(matching query: Query) -> [T]
func loadObject<T>(withID id: String) -> T?
func save<T>(_ object: T)
}
, где Query
- это структура, которая имеет спецификаторы фильтра и сортировки.
Затем, учитывая постоянную структуруНапример, Realm или CoreData, я могу просто поддерживать этот протокол следующим образом:
extension NSManagedObjectContext: Database {
...
}
extension Realm: Database {
...
}
extension MockedDatabase: Database {
...
}
extension UITestingDatabase: Database {
...
}
Проблема возникает, когда я хочу использовать CoreData.
Если мы посмотрим на метод:
func loadObjects<T>(matching query: Query) -> [T]
У меня нет возможности «привести» T к NSManagedObject.
Например, моя желаемая реализация может выглядеть примерно так:
extension NSManagedObjectContext: Database {
func loadObjects<T>(matching query: Query<T>) -> [T] {
// you need a fetch request for these models. This guard statement compiles. How do we make it work with NSFetchRequestResult however?
guard T.self is NSManagedObject.Type else {
return []
}
// This line below Fails compiling. Type 'T' does not conform to protocol 'NSFetchRequestResult'
var request = NSFetchRequest<T>(entityName: String(describing: T))
// then set sortDescriptors and predicate, etc.
var objects: [T] = []
self.performAndWait {
do {
if let results = try self.fetch(request!) as? [T] {
objects = results
}
} catch let error {
print("Error fetching: \(error.localizedDescription)")
}
}
return objects
}
}
Так что, если я могу определить, является ли T типом своего рода NSManagedObject, то возможно ли создать экземпляр NSFetchRequest путем «приведения» T к чему-то, что будет работать?Казалось бы, я не могу привести или заставить T быть чем-либо.
База данных является технологически независимым протоколом и поэтому не должна ничего знать о Core Data.Я хотел бы сделать это в случае, если мне нужно изменить структуру хранения данных.
Как я могу сделать это в Swift?Должен ли я добавить к протоколу Model
, чтобы вернуть дополнительные параметры, которые будут использоваться для заданных платформ, которые я буду поддерживать?Или заставить их поддерживать NSFetchRequestResult?Я бы предпочел, чтобы только реализация протокола требовала внимания к деталям структуры персистентности.