编辑:特别使用Swift Generics
我想为所有实体使用countAll()函数,我希望通过编写一个通用函数来实现这一点。
以下处理一个名为'Event'的实体,但我想处理一个名为'T'的实体。
我不确定如何编写这样的通用函数。有人可以帮忙吗?
func countAll() -> Int {
let request: NSFetchRequest<Event> = Event.fetchRequest()
do {
return try persistentContainer.viewContext.count(for: request)
} catch {
XCTAssert(false, "Core Data failed to fetch with error: " + error.localizedDescription)
return 0
}
}
这是我遇到错误之前最接近的:
func count<T: NSFetchRequestResult>(entityName: String) -> Int {
let request = NSFetchRequest<T>(entityName: entityName)
do {
return try persistentContainer.viewContext.count(for: request)
} catch {
XCTAssert(false, "Core Data failed to fetch with error: " + error.localizedDescription)
return 0
}
}
答案 0 :(得分:3)
泛型函数的合适替代方法是协议扩展和类方法
protocol Fetchable
{
associatedtype FetchableType: NSManagedObject = Self
static var entityName : String { get }
static func countAll(in persistentContainer: NSPersistentContainer) throws -> Int
}
extension Fetchable where Self : NSManagedObject, FetchableType == Self
{
static var entityName : String {
return NSStringFromClass(self).components(separatedBy: ".").last!
}
static func countAll(in persistentContainer: NSPersistentContainer) throws -> Int
{
let request = NSFetchRequest<FetchableType>(entityName: entityName)
return try persistentContainer.viewContext.count(for: request)
}
}
好处是你可以在类上调用方法,只需让你的NSManagedObject
子类采用协议。
do {
try Event.countAll(in: persistentContainer)
} catch { print(error) }
答案 1 :(得分:2)
您可以传递托管对象类而不是NSFetchRequestResult
通用函数:
func countAll<T: NSManagedObject>(entity: T.Type) -> Int {
let entityName = String(describing: entity)
let request = NSFetchRequest<T>(entityName: entityName)
do {
return try thePersistentContainer.viewContext.count(for: request)
} catch {
print(error.localizedDescription)
return 0
}
}
let count = countAll(entity: YourEntity.self)
另一种方法是在NSManagedObject
上定义扩展方法
(与How can I create instances of managed object subclasses in a NSManagedObject Swift extension?中的内容类似):
extension NSManagedObject {
class func countAll() -> Int {
let eName = String(describing: self)
let request = NSFetchRequest<NSFetchRequestResult>(entityName: eName)
do {
return try thePersistentContainer.viewContext.count(for: request)
} catch {
print(error.localizedDescription)
return 0
}
}
}
let count = YourEntity.countAll()