我正在研究Swift和核心数据,我计划在模型上使用一个简单的包装器。
此时,协议和扩展名如下所示:
protocol CRUD {
associatedtype T: NSManagedObject
var context: NSManagedObjectContext { get }
var items: [T]! { get set }
func getAll() -> [T]
mutating func addOrUpdate(_ item: T) -> T
mutating func delete(_ item: T)
}
extension CRUD where T: NSManagedObject {
var context: NSManagedObjectContext {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
}
func save() {
do {
try context.save()
} catch {
fatalError("Saving of \(String(describing: self)) failed")
}
}
func getAll() -> [T] {
let fetchRequest = NSFetchRequest<T>(entityName: String(describing: T.self))
let list: [T]
do {
list = try context.fetch(fetchRequest)
} catch {
fatalError("Fetching of \(String(describing: self)) failed")
}
return list
}
mutating func delete(_ item: T) {
if let index = items.index(of: item) {
items.remove(at: index)
}
context.delete(item)
save()
}
mutating func addOrUpdate(_ item: T) -> T {
if (items.contains(item)) {
items.append(item)
}
save()
return item
}
}
每个模型都声明如下:
class TaskModel : CRUD {
typealias T = Task
var items: [Task]!
init() {
self.items = getAll()
}
}
这段代码与OOP的原理相对应多少(特别是,我可以将此协议称为DAO模式的实现)吗?需要这样的包装吗?或者Core Data是否意味着在代码中直接使用模型?
未来可能会出现哪些问题?
我将非常感谢更有经验的iOS开发人员的建议。先感谢您。
协议可能对于这种功能来说太多了,因为协议的主要目标仍然是多态。您可以使用通用结构:
struct CRUD<T: NSManagedObject> {
var context: NSManagedObjectContext {
return (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
}
var items = [T]()
// let's provide two approaches for initialization
init() {
self.init(items: getAll())
}
init(items: [T]) {
self.items = items
}
func save() {
do {
try context.save()
} catch {
fatalError("Saving of \(String(describing: self)) failed")
}
}
func getAll() -> [T] {
let fetchRequest = NSFetchRequest<T>(entityName: String(describing: T.self))
let list: [T]
do {
list = try context.fetch(fetchRequest)
} catch {
fatalError("Fetching of \(String(describing: self)) failed")
}
return list
}
mutating func delete(_ item: T) {
if let index = items.index(of: item) {
items.remove(at: index)
}
context.delete(item)
save()
}
mutating func addOrUpdate(_ item: T) -> T {
if (items.contains(item)) {
items.append(item)
}
save()
return item
}
}
然后,您可以在课堂上使用它:
class TaskModel {
// making sure no-one from outside can mutate our CRUD
private(set) lazy var crud = CRUD<Task>()
init() {
// nothing to do here, the items are already populated
}
}
let model = TaskModel()
// the following won't compile
model.crud.delete(someTask)
IMO,这更好地传达了Facade over CoreData的意图。