NSFetchedResultsController - 在展开可选值时意外发现 nil

Posted

技术标签:

【中文标题】NSFetchedResultsController - 在展开可选值时意外发现 nil【英文标题】:NSFetchedResultsController - unexpectedly found nil while unwrapping an Optional value 【发布时间】:2015-10-09 15:09:54 【问题描述】:

我正在使用NSFetchedResultsController 来填充我的 TableView。我有一个实体“HubProfile”,其属性为:“Name”和“HubID”

问题: NSFetchedResultsController 即将到来 nil。奇怪的是,当我在viewDidLoadcellForRowIndexPath 方法中打印fetchedResultsController 时——它给出了一个值。但是在numberOfRowsInSection 方法中,fetchedResultsControllernil 并且应用程序崩溃了。

此外,数据已经保存在 CoreData 中。我在 SQLite 浏览器中看到过——所以有数据要加载

似乎无法弄清楚为什么。

下面是我的代码:

 class StudentsController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate
 
  let managedContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
  var fetchedResultsController: NSFetchedResultsController!

  override func viewDidLoad() 
    super.viewDidLoad()

  //FETCH REQUESTS
    let fetchRequest = NSFetchRequest(entityName: "HubProfile")
    let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    fetchRequest.predicate = NSPredicate(format: "hubID = %@", hubID!)

    fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedContext, sectionNameKeyPath: nil, cacheName: nil)

    fetchedResultsController.delegate = self

    do
    
        try! fetchedResultsController.performFetch()
    

    print(fetchedResultsController)  //THIS IS NOT NIL
    

   //TABLEVIEWDATASOURCE PROTOCOL:

   func numberOfSectionsInTableView(tableView: UITableView) -> Int 
    return 1
   

   func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    print(fetchedResultsController) // THIS IS NIL
    let sectionInfo = fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo
    return sectionInfo.numberOfObjects
   

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! StudentsCell!
    print(fetchedResultsController)  //THIS is NOT Nil
    let hubProfile = fetchedResultsController.objectAtIndexPath(indexPath) as! HubProfile
    cell.nameLabel?.text = hubProfile.name 
    return cell

【问题讨论】:

所以表视图试图在任何数据出现之前访问“fetchedResultsController”。所以你可以做的是首先检查它是否为空,然后在viewdidload中获取后放置一个tableview.reload。当获取数据时,它将重新加载 tableview。 并且每当你使用可选值时,尝试安全地解包,然后你就不会得到这个错误。 尝试了重新加载数据..没有工作..正如我在 viewDidLoad 中所说..我已经放了一个 print(fetchedResultsController)..工作正常..问题只在 numberOfRowsInSection方法。 通过以下所有更改使viewDidLoad 成为可选应该可以解决问题,出于好奇,我想查看tableView:numberOfRowsInSection: 调用的回溯,其中fetchedResultsController 为nil,以及无论是在 viewDidLoad 之前还是之后调用。 我不确定我是否理解正确..我将fetchedResultsController 声明设为可选..它仍然崩溃...因为“__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'” ...基本上fetchedResultsController 为零.. 【参考方案1】:

tableView 可能在 fetchResultsController 有机会加载之前已经加载。因此,在执行 Fetch() 后立即重新加载表:

  do

    try! fetchedResultsController.performFetch()
    tableView.reloadData()


print(fetchedResultsController)  //THIS IS NOT NIL

然后在您的 tableView 函数中检查 fetchedResultsController 是否为 nil,如果是,则给它一些其他值(在本例中为 0),当获取完成后重新加载表时,该函数将从您的fetchResultsController(当它是 != nil 时):

    override func numberOfSections(in tableView: UITableView) -> Int 
           return fetchedResultsController.sections?.count ?? 0
    

【讨论】:

以上是关于NSFetchedResultsController - 在展开可选值时意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章

在 Core Data 应用程序中调用 performFetch 后,是不是需要手动更新表视图?