unrecognized selector sent to instance with Coreda

2020-02-11 04:42发布

I keep getting this error whenever I try to update a value of core data model. Here is my model

import Foundation
import CoreData

@objc(Habit)
class Habit: NSManagedObject {

    @NSManaged var name: String
    @NSManaged var trackingType: NSNumber
}

Here is my code tableViewCell

override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        if selected {
            self.accessoryType = UITableViewCellAccessoryType.Checkmark
            if self.habit? != nil {
                self.habit?.trackingType = index

            }

        } else {
            self.accessoryType = UITableViewCellAccessoryType.None
        }
        // Configure the view for the selected state

    }

I keep getting error "Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Habit setTrackingType:]: unrecognized selector sent to instance 0x7fdcbb002c90'"

at line self.habit?.trackingType = index

I am struggling to fix this for last 2 days.

Edit:

The model habit is initialized in below way

func getHabits() -> [AnyObject]{
        let entityDescription =
        NSEntityDescription.entityForName("Habit",
            inManagedObjectContext: managedObjectContext!)

        let request = NSFetchRequest()
        request.entity = entityDescription
//        
//        let pred = NSPredicate(format: "(trackingType != -1)")
//        request.predicate = pred

        var error: NSError?

        var objects = managedObjectContext?.executeFetchRequest(request,
            error: &error)

        return objects!;
    }

The returned list is used everywhere in the app. Basically I fetch and item from the list and update its attributes and then save it again

1条回答
家丑人穷心不美
2楼-- · 2020-02-11 05:14

Ok so the reason you are getting the error is most certainly because the object referenced by self.habit is not a Habit object. The easiest way to find out what the object really is is to call:

print(NSStringFromClass(habit.class))

With core data and custom NSManagedObjects you need to make sure that the entity: 'Habit' (in your data model) has a class set to Habit. This makes sure that Core Data casts your fetched objects with an entity description of 'Habit' to the Habit class. If you are not doing this then the getHabits func will be returning an array of NSManagedObjects not an array of Habits.If this is the case then the code: println(NSStringFromClass(habit.class)) will print "NSManagedObject" to the debugger.

As a side note, you really need to check for errors when you fetch objects from a Core Data database. Add the lines:

if objects? == nil {
    print("An error occurred \error.localisedDescription")
}

Please forgive my swift if there are any errors, I normally use Objective-C.

EDIT: In order to correct Failed to call designated initializer on NSManagedObject class 'X' error. This error is fired when you do not correctly instantiate an NSManagedObject. You must not call [[MyManagedObject alloc] init]; you have to call initWithEntity:insertIntoManagedObjectContext instead:

MyManagedObject *obj = [[MyManagedObject alloc] initWithEntity:[NSEntityDescription entityForName:@"MyManagedObject" inManagedObjectContext:context] insertIntoManagedObjectContext:context];

If you do not want the object obj to be inserted into a context you can pass through a nil context argument. However, if you want undo management and the ability to save the object to the database it needs to be associated with a context.

If you want to have a custom initialisation of an object then you can override the awakeFromInsert and awakeFromFetch methods/functions.

查看更多
登录 后发表回答