需要通用的 FetchedResultsController 构建器 (Swift)

Need generic FetchedResultsController builder (Swift)

我创建了一个构建 frc 的方法:

private func buildFRC<T:NSManagedObject>(entity: T, sortKey: String) 
    -> NSFetchedResultsController<T>? {

    let fetchRequest: NSFetchRequest = T.fetchRequest()
    let sortDescriptor1 = NSSortDescriptor(key: sortKey, ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor1]

    searchContext.reset()

    var frc: NSFetchedResultsController<T>? =
        NSFetchedResultsController<T>(
        fetchRequest:            fetchRequest as! NSFetchRequest<T>,
        managedObjectContext:   searchContext,
        sectionNameKeyPath:     nil,   
        cacheName:              nil)   
    frc!.delegate = self                

    try? frc!.performFetch()
    return frc
}

我想在闭包中调用这样的东西:

self.frc = self.buildFRC(entity: ObjectName, sortKey: "trackName")

但我收到此错误:

"Cannot convert value of type 'ObjectName.Type' to expected argument type 'NSManagedObject'".

然而,ObjectNameNSManagedObject 的 class 名称。我试过自己 但最终我只是一直在追逐错误。

您的函数声明并不意味着完全您认为的那样。

private func buildFRC<T:NSManagedObject>(entity: T, sortKey: String) -> NSFetchedResultsController<T>? 

这意味着 T 必须是 NSManagedObject 的子类,并且第一个参数必须是 T 的一个实例。当你这样称呼它时

self.frc = self.buildFRC(entity: ObjectName, sortKey: "trackName")

...当您的声明需要一个实例时,您将子类作为第一个参数传入。

修复起来并不难,因为您不需要将 T 作为参数包含在内。通常,Swift 泛型不需要您将类型作为参数传递——类型来自函数的使用方式。删除该参数并将声明重写为

private func buildFRC<T:NSManagedObject>(sortKey: String) -> NSFetchedResultsController<T>? {

然后用类似

的方式调用函数
self.frc: NSFetchedResultsController<ObjectName>? = self.buildFRC(sortKey: "trackName")

Swift 会计算出 T 在那个调用中代表 ObjectName 并且代码会工作。

顺便说一句,您对 searchContext.reset() 的调用有点危险,可能不需要。如果您从上下文中获取一些对象,然后稍后调用此函数,reset 将导致所有那些先前获取的对象变得无效。使用它们会使您的应用程序崩溃。