2

When I'm trying to delete objects from my core data I get this error:

fatal error: NSArray element failed to match the Swift Array Element type

and I have to idea why this happens. My table view is divided into sections, maybe that has something to do with it? I have never had any problem with deleting core-data from a table view before, so this is very strange to me.

My code looks like this:

var userList = [User]()
var usernames = [String]()

        viewDidLoad(){
        let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
        let context:NSManagedObjectContext = appDel.managedObjectContext!

        let fetchReq = NSFetchRequest(entityName: "User")
        let en = NSEntityDescription.entityForName("User", inManagedObjectContext: context)
        let sortDescriptor = NSSortDescriptor(key: "username", ascending: true)
        fetchReq.sortDescriptors = [sortDescriptor]
        fetchReq.propertiesToFetch = ["username"]
        fetchReq.resultType = .DictionaryResultType

        userList = context.executeFetchRequest(fetchReq, error: nil) as [User]
}


        func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

            let editedCell = self.tv.cellForRowAtIndexPath(indexPath)

            let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
            let context:NSManagedObjectContext = appDel.managedObjectContext!

            if editingStyle == UITableViewCellEditingStyle.Delete {

                if let tv = tableView as Optional{

                    let textLbl = editedCell?.textLabel?.text
                    let ind = find(usernames, textLbl!)! as Int

                    context.deleteObject(userList[ind] as NSManagedObject)

                    userList.removeAtIndex(ind)

                    tv.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
                }
          } 
    }

In my code, the usernames array is just an array with all the usernames retrieved from core data in userList.

The errors appears last in my code where I'm trying to delete the object from the context, and from the userList; it's the same error in both lines. I've tried casting my userList as Array<AnyObject> but then I also got an runtime error with zero clues to what was wrong.

Any suggestions on how to solve this issue would be very appreciated.

9
  • Is User an NSManagedObject subclass? If so you shouldn't need "as NSManagedObject" in your delete - the fact that you have it makes me suspect that your subclass isn't registered and you are getting plain NSManagedObjects, not User objects which is why you are getting the array type error. Try setting userList as [NSManagedObject] rather than [User] Commented Jan 24, 2015 at 23:10
  • @Paulw11 I now declare the userList as userList:[NSManagedObject] and retrieve it "as [NSManagedObject]", I also tried removing the "as NSManagedObject" in my delete. It's still not working, and yes, User is a subclass of NSManagedObject. Commented Jan 24, 2015 at 23:17
  • Can you set a breakpoint and examine the array? Commented Jan 24, 2015 at 23:18
  • @Paulw11 I could, but I'm really not sure what I would be looking for. Commented Jan 24, 2015 at 23:19
  • What type is in the array? Swift is complaining that it isn't what you said it was going to be Commented Jan 24, 2015 at 23:19

1 Answer 1

3

With

fetchReq.resultType = .DictionaryResultType

the fetch request

userList = context.executeFetchRequest(fetchReq, error: nil) as [User]

returns an array of NSDictionary objects, not an array of User objects, and you are just deluding the compiler with the cast as [User].

For performance reasons, the Swift runtime does not verify at this point if all array elements are really User objects, so this assignment succeeds. But as soon as you access an array element, for example with

userList[ind]

then you get the runtime exception because the element type (NSDictionary) does not match the array type (User).

Also you cannot cast a dictionary back to the managed object, so this will never work:

context.deleteObject(userList[ind] as NSManagedObject)

The best solution is probably just to remove the lines

fetchReq.propertiesToFetch = ["username"]
fetchReq.resultType = .DictionaryResultType

so that the fetch request returns an array of User objects, and adjust the rest of your code if necessary.

You might have a look again at the two different solutions proposed in https://stackoverflow.com/a/28055573/1187415. The first one returns an array of managed objects, and the second one an array of dictionaries. What you have done here is to mix the solutions by setting the result type to .DictionaryResultType, but treating the result as an array of managed objects.

Remark: I would recommend to use a NSFetchedResultsController to display the results of a Core Data fetch request in a table view. The FRC efficiently manages the table view data source (with optional grouping into sections), and updates the table view automatically if the result set changes.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.