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

时间:2018-11-16 01:44:34

标签: swift core-data nsmanagedobjectmodel

我创建了一种构建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")

但我收到此错误:

  

“无法将类型'ObjectName.Type'的值转换为预期的参数类型'NSManagedObject'”。

但是,ObjectNameNSManagedObject的类名。我尝试过 但最终我还是不断追逐错误。

1 个答案:

答案 0 :(得分:1)

您的函数声明并不等于您认为的那样。

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将导致所有这些先前获取的对象变为无效。使用它们会使您的应用程序崩溃。