Search code examples
swiftcore-datansfetchedresultscontroller

Why does my fetchedResultsController.ObjectAtIndexPath return NSFetchRequestResult instead of an object?


I thought this would be a straight forward thing to do but for some unknown reason, I can't access the properties of the object at a given indexPath.

I'm trying to create my app using MVVM as much as possible (still using Swift 2.3) so my UITableViewController is backed by a view model called FormulasViewModelFromLiftEvent. The view model is initialized with a fetchedResultsController like so:

struct FormulasViewModelFromLiftEvent {
    var modelLiftEvent: LiftEventProtocol
    var fetchedResultsController: NSFetchedResultsController
    let dataManager = CoreDataHelper()

    init(withLiftEvent liftEventModel: LiftEventProtocol) {
        self.modelLiftEvent = liftEventModel

        let moc = modelLiftEvent.context
        fetchedResultsController = dataManager.fetchSelectableFormulas(moc)
    }
}

The results are a collection of Formula objects.

Back in my UITableViewController, I have this extension in which I'm putting the required table view methods. I can access the fetchResultsController of the view model within the numberOfSectionsInTableView and numberOfRowsInSection methods with no problems. In cellForRowAtIndexPath, I want to populate the cell with the formula name property but I can't access any of the properties of the objectAtIndexPath:

extension FormulasViewController: UITableViewDataSource {

  override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    guard let sections = viewModel.fetchedResultsController.sections else { return 0 }
    return sections.count
  }

  override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard let section = viewModel.fetchedResultsController.sections?[section] else { return 0 }
    return section.numberOfObjects
  }

  override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cellViewModel: SelectionsRepresentable

        let cell = tableView.dequeueReusableCellWithIdentifier("formulasCell", forIndexPath: indexPath)

        let formula = viewModel.fetchedResultsController.objectAtIndexPath(indexPath)
        let formulaName = formula.    <-- None of the Formula properties are available

        cellViewModel = FormulaSelectionViewModel(defaultFormulaName: formulaName)

        cell.textLabel?.text = cellViewModel.text
        cell.accessoryType = cellViewModel.accessoryType

        return cell
      }
}

According to the documentation, let formula = viewModel.fetchedResultsController.objectAtIndexPath(indexPath) should return the Formula object at the given index path in the fetch results. But formula thinks it's an NSFetchRequestResult and so of course I can't access any Formula properties.


Solution

  • NSFetchRequestResult is the protocol NSManagedObject, NSDictionary, NSManagedObjectID and NSNumber conform to. You need to type cast the object:

    let formula = viewModel.fetchedResultsController.objectAtIndexPath(indexPath) as! Formula