ios - 我想要一个用于核心数据的通用 fetchedResultsController 来支持多个模型

标签 ios swift generics core-data nsfetchedresultscontroller

我已经简化了我的问题以使问题变得更容易,所以希望我发布的代码足够了。

我的目标是使用一个可以支持 CoreData 中的多个模型的类,这样我就可以避免为每个类重新创建相同的内容。

class FRC<T> where T: NSManagedObject {
    let context: NSManagedObjectContext

    fileprivate lazy var fetchedResultscontroller: NSFetchedResultsController<T> = { [weak self] in
        guard let this = self else {
            fatalError("lazy property has been called after object has been descructed")
        }
        guard let request = T.fetchRequest() as? NSFetchRequest<T> else {
            fatalError("Can't set up NSFetchRequest")
        }
        request.sortDescriptors = [NSSortDescriptor(key: "key", ascending: true)]
        return NSFetchedResultsController<T>(fetchRequest: request,
                                             managedObjectContext: this.context,
                                             sectionNameKeyPath: nil,
                                             cacheName: nil)
        }()

    init(context: NSManagedObjectContext) {
        self.context = context
    }
}

enum ModelType {
    case modelA
    case modelB
}

class GenericDataModel: NSObject {
    let container: NSPersistentContainer
    // STUPID!!!
    var frcA: FRC<ModelA>?
    var frcB: FRC<ModelB>?

    init(modelType: ModelType) {
        container = NSPersistentContainer(name: "MyContainer")
        container.loadPersistentStores { _, error in /* Handle */ }
        // Below here is ugly!
        switch modelType {
        case .modelA:
            frcA = FRC<ModelA>(context: container.viewContext)
        case .modelB:
            frcB = FRC<ModelB>(context: container.viewContext)
        }
    }
}

extension GenericDataModel: NSFetchedResultsControllerDelegate {
    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
                    didChange anObject: Any,
                    at indexPath: IndexPath?,
                    for type: NSFetchedResultsChangeType,
                    newIndexPath: IndexPath?) {
        // Handle
    }
}

看来我能做的最好的事情就是在 GenericDataModel 类中为不同的模型类创建多个变量,这对于大量模型类来说无法很好地扩展。

但是,尝试为 FRC 类创建单个局部变量始终失败,我无法理解为什么。

我是泛型新手,所以很可能我只是做了一些愚蠢的事情。

最佳答案

这不是一个坏主意。我已经做到了: https://github.com/jon513/FetchedResultsControllerNeverCrash/blob/master/coreDataNeverCrash/FetchedResultsControllerManager.swift

这实现了一种方法,使核心数据在同时进行删除和更新时永远不会崩溃(请参阅 App crashes after updating CoreData model that is being displayed in a UITableView ),并使 API 更容易一些。

要使用它,请创建一个带有 fetchRequest、上下文和委托(delegate)的 FetchedResultsControllerManager。

委托(delegate)实现很简单:

extension ViewController : FetchedResultsControllerManagerDelegate {
    func managerDidChangeContent(_ controller: NSObject, change: FetchedResultsControllerManagerChange) {
        change.applyChanges(collectionView: collectionView)
    }
}

由于泛型的原因,我无法让委托(delegate)返回正确的类,但我从来不需要测试除 equal 以外的任何东西,所以它从来没有打扰我。如果您可以让它与泛型一起使用,我很乐意收到拉取请求。

关于ios - 我想要一个用于核心数据的通用 fetchedResultsController 来支持多个模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53420904/

相关文章:

iphone - RackSpace身份验证

ios - UITableView:使用 moveRowAtIndexPath:toIndexPath: 和 reloadRowsAtIndexPaths:withRowAnimation: 一起出现损坏

iphone - 在Objective-C中,与类方法相比,拥有单例有什么优势?

ios - 在 Swift 中将自定义对象保存到 NSUserDefaults

c# - 如何实例化嵌套 IList<T> 的 IList<T>?

java - Java 方法分派(dispatch)如何与泛型和抽象类一起工作?

generics - 从 lambda 参数推导时,Kotlin 泛型失败

ios - 为 UITextView 调整FontSizeToFitWidth

ios - swift ios 使用 alamofire 将 curl 转换为 swift curl

ios - 当应用程序处于后台时在 Swift 2.0 Xcode 7 中显示警报消息