Swift: Could not cast value of type 'NSManagedObject_' to 'dataModel.Entity'

4k views Asked by At

I don't really know what I have to explain or not, don't hesitate to ask me more code or explanations if needed.. I'm trying to use a CoreData to stock datas gotten from an http POST request and then print them on an UITableView.

I successfully get datas from the JSON and send them to the database. The problem is when I try to send the datas from the database to the UITableView.

It's my first time with the Core Data, so to understand how it works, I have followed this tutorial I adapted to my situation: https://www.youtube.com/watch?v=UniafUWsvLg

This is the Entity in which I'm working:

import Foundation
import CoreData

class Task: NSManagedObject {

    @NSManaged var summary: String
    @NSManaged var status: String
    @NSManaged var responsable: String
    @NSManaged var id: String
    @NSManaged var detail: String
    @NSManaged var date: String
    @NSManaged var context: String

}

This is a part of the code preparing the work on the CoreData, I have some comments on it:

//Preparing variables used to get and send datas from DB
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var nTask: Task? = nil
var frc : NSFetchedResultsController = NSFetchedResultsController()

func getFetchedResultsController() -> NSFetchedResultsController{
    frc = NSFetchedResultsController(fetchRequest: taskFetchRequest(), managedObjectContext: context!, sectionNameKeyPath: nil, cacheName: nil)
    return frc
}
func taskFetchRequest() -> NSFetchRequest {
    //On which Entity are we working?
    let fetchRequest = NSFetchRequest(entityName: "Task")
    //Which attribute get the Order by. There summary as Ascending
    let sortDescriptor = NSSortDescriptor(key: "summary", ascending: true)
    fetchRequest.sortDescriptors = [sortDescriptor]
    return fetchRequest
}

Now I have declared this, I set on the viewDidLoad the delegate of the getFetchedResultsController to self:

override func viewDidLoad() {
    super.viewDidLoad()

    frc = getFetchedResultsController()
    frc.delegate = self
    frc.performFetch(nil)
}

This is how I create the link to the database to get datas from:

//Link creation to SQLite DB
        let context = self.context
        let ent = NSEntityDescription.entityForName("Task", inManagedObjectContext: context!)
        let nTask = Task(entity: ent!, insertIntoManagedObjectContext: context)

then I populate my nTask with String extracted from the JSON, I save the context and I reload the DataBase:

for dict in json2 {
    var apps = [String]()


    if let summary = dict["summary"] as? String{
        nTask.summary = summary
    }


    if let description = dict["description"] as? String{
        nTask.detail = description
    }


    if let context = dict["context"] as? String{
        nTask.context = context
    }


    if let due = dict["due"] as? String {
        nTask.date = due
    }

    if let status = dict["status"] as? String{
        nTask.status = status
    }

    if let responsible = dict["responsible"] as? String{
        nTask.responsable = responsible
    }

    if let id = dict["id"] as? String{
        nTask.id = id
    }

}
context?.save(nil)
println(nTask)
self.tableView.reloadData()

When we use a TableView, we have to declare cellForRowAtIndexPath and numberOfRowsInSection, these are them:

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

    var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("customTableViewCell") as! UITableViewCell
    let task = frc.objectAtIndexPath(indexPath) as! Task
    cell.textLabel?.text = task.summary
    var detail = task.detail
    var context = task.context
    var due = task.date
    var status = task.status
    var responsible = task.responsable

    cell.detailTextLabel?.text = "Contexte: \(context), Detail: \(detail), Status: \(status), Ending date: \(due)"

    return cell
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    let numberOfRowsInSection = frc.sections?[section].numberOfObjects
    return numberOfRowsInSection!

}

The error is line let task = frc.objectAtIndexPath(indexPath) as! Task on my cellForRowAtIndexPath.

The complete error is: Could not cast value of type 'NSManagedObject_Task_' (0x79ebd190) to 'TaskManager.Task' (0xa1f08).

I search for more than half day and no results. I really don't understand what's happening to me...

I'm sorry to give so much code but I haven't any idea of where or why I have this error, so I have to give as informations as possible..

Thanks you so much for having read to the end, thank you for your help.

Regards.

Edit:

I have finally solved my problem by doing several things. I don't really know which one solved... I added the annotation @objc(Task) on my Task class,on my DataModel I changed the class to Task, checked my NSManagedObjectModel was let modelURL = NSBundle.mainBundle().URLForResource("TaskManager", withExtension: "momd")! and the url let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("TaskManager.sqlite") on the AppDelegate..

Thank you for your help.

2

There are 2 answers

2
eliasRuizHz On

Try:

let task = frc.objectAtIndexPath(indexPath) as NSManagedObject

Perhaps the real problem you have is not the extraction in its "cellForRowAtIndexPath" is in its "FOR":

for dict in json2 {
...
if let summary = json2["summary"] as? String{
    nTask.summary = summary
}
...

You it is seeking "summary" of "dict" when you should get it from "json2"

0
Julien Perrenoud On

I experienced a similar issue, and in my case what worked was to add this @objc(NameOfClass) above my core data class definition. Thank you!