简体   繁体   English

重构NSFetchedResultsController

[英]Refactoring NSFetchedResultsController

This code now sits in a UIViewController : 现在,此代码位于UIViewController

lazy var categoryFRC: NSFetchedResultsController<Category> = {
    let fetchRequest: NSFetchRequest<Category> = Category.fetchRequest()
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "text", ascending: true)]
    let appDelegate = (UIApplication.shared.delegate) as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext
    let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
    frc.delegate = self
    do {
        try frc.performFetch()
    } catch {
        fatalError("Failed to initialize FetchedResultsController: \(error)")
    }
    return frc
}()

And this is the way I refer to the fetched categories with a for-loop: 这就是我通过for循环引用获取的类别的方式:

let category = (self.categoryFRC.fetchedObjects?[index])! as Category

I would like to access the same CoreData entity from a different ViewController . 我想从不同的ViewController访问相同的CoreData实体。

  1. May I know what is the right way to restructure my code? 我可以知道重组代码的正确方法是什么吗?

  2. Do I create a new class? 我要创建一个新班吗?

  3. And how do I handle the NSFetchedResultsControllerDelegate ? 我该如何处理NSFetchedResultsControllerDelegate

  4. Must all the ViewControllers referring to the fetchedResults be a subclass of NSFetchResultsControllerDelegate ? 必须将所有ViewControllersfetchedResults是一个子类NSFetchResultsControllerDelegate

What I've done is pull all non-view rendering/user event handling from ViewControllers and put that logic into another class. 我所做的是从ViewControllers中提取所有非视图渲染/用户事件处理,并将该逻辑放入另一个类中。 In your case you want to create a new class and put the categoryFRC logic into the new class 在您的情况下,您想创建一个新类并将categoryFRC逻辑放入新类中

class DataController {
  lazy var categoryFRC: NSFetchedResultsController<Category> = {
  let fetchRequest: NSFetchRequest<Category> = Category.fetchRequest()
  fetchRequest.sortDescriptors = [NSSortDescriptor(key: "text", ascending: true)]
  let appDelegate = (UIApplication.shared.delegate) as! AppDelegate
  let context = appDelegate.persistentContainer.viewContext
  let frc = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
  frc.delegate = self

  do {
    try frc.performFetch()
  } catch {
    fatalError("Failed to initialize FetchedResultsController: \(error)")
  }

  return frc
  }()
}

Then in the ViewController store an instance of DataController: 然后在ViewController中存储DataController的实例:

class ViewController {
  var dataController : DataController!

  func viewDidLoad() {
    dataController = DataController()
    dataController.categoryFRC.delegate = <Class that adopts NSFetchedResultsControllerDelegate>
  }
}

Other observations: 其他观察:

  • Create another class that adopts NSFetchedResultsControllerDelegate. 创建另一个采用NSFetchedResultsControllerDelegate的类。 Then set the categoryFRC.delegate to the new class. 然后将categoryFRC.delegate设置为新类。 This way the new class is responsible for the FRC delegate methods, not the view controller. 这样,新类负责FRC委托方法,而不负责视图控制器。

  • pull the do/try/catch around the frc.performFetch() from the lazy categoryFRC definition. 从懒惰的类别FRC定义中拉出围绕frc.performFetch()的do / try / catch。 Are you sure that you want to perform a fetch each time you access categoryFRC? 您确定每次访问categoryFRC都要执行提取吗? I'd put the do/try/catch logic into a new function. 我会将do / try / catch逻辑放入一个新函数中。

  • Look at your for loop, what happens if fetchedObjects? 看一下您的for循环,如果fetchedObjects会发生什么? is nil? 是零吗? Wouldn't you crash because you are then unwrapping a nil value? 您是否会因为解开nil值而崩溃?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM