2
votes

I am getting this error Thread 1: Exception: "-[Tasks initWithCoder:]: unrecognized selector sent to instance 0x60000034da40" whenever I try to load my core data object.

  • I have two entities (Tasks, Goal) with inverse many to many relationship.
  • The goal entity has an attribute of transformable with a custom class [NSManagedObject] of task. I think this creates an issue when loading. but surprisingly when I save my context it doesn't crash

Goal Entity

Task Entity

Here us my subclass codegen of goal entity

extension Goal {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Goal> {
        return NSFetchRequest<Goal>(entityName: "Goal")
    }

    @NSManaged public var date: String?
    @NSManaged public var goalTasks: [NSManagedObject]?
    @NSManaged public var isComplete: Bool
    @NSManaged public var name: String?
    @NSManaged public var nsdate: Date?
    @NSManaged public var tasks: NSSet?

}

// MARK: Generated accessors for tasks
extension Goal {

    @objc(addTasksObject:)
    @NSManaged public func addToTasks(_ value: Tasks)

    @objc(removeTasksObject:)
    @NSManaged public func removeFromTasks(_ value: Tasks)

    @objc(addTasks:)
    @NSManaged public func addToTasks(_ values: NSSet)

    @objc(removeTasks:)
    @NSManaged public func removeFromTasks(_ values: NSSet)

}

Here us my subclass codegen of tasks entity

import Foundation
import CoreData


extension Tasks {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Tasks> {
        return NSFetchRequest<Tasks>(entityName: "Tasks")
    }

    @NSManaged public var date: String?
    @NSManaged public var importValue: Int16
    @NSManaged public var isComplete: Bool
    @NSManaged public var list: String?
    @NSManaged public var name: String?
    @NSManaged public var nsdate: Date?
    @NSManaged public var goals: NSSet?

}

// MARK: Generated accessors for goals
extension Tasks {

    @objc(addGoalsObject:)
    @NSManaged public func addToGoals(_ value: Goal)

    @objc(removeGoalsObject:)
    @NSManaged public func removeFromGoals(_ value: Goal)

    @objc(addGoals:)
    @NSManaged public func addToGoals(_ values: NSSet)

    @objc(removeGoals:)
    @NSManaged public func removeFromGoals(_ values: NSSet)

}

here is how I am inserting a new goal object

@IBAction func setGoal(_ sender: Any) {

// Adding a task to the array
let df = DateFormatter()
    df.dateFormat = "dd-MM-yyyy" // assigning the date format
 let goalVC = GoalViewController()

 let now = df.string(from: Date())
 let newGoal = NSEntityDescription.insertNewObject(forEntityName: "Goal", into: context) as! Goal
 newGoal.setValue(goalTitle.text!, forKey: "name")
 newGoal.setValue(false, forKey: "isComplete")
 newGoal.setValue(goalDate, forKey: "nsdate")
 newGoal.setValue(now, forKey: "date")
 newGoal.setValue(goalSubTasks, forKey: "goalTasks")
    


do {
    try
    context.save()
    homeVC.loadGoals()
    print(newGoal)
    
    } catch {
    print("Problem while saving")
    }
    self.dismiss(animated: true, completion: nil)
}

and here the app crashes when this function is called where I load my load my goals into allGoals (array of [NSManagedObject])

    func loadGoals(){
    allGoals.removeAll()
    let requestGoal = NSFetchRequest<NSFetchRequestResult>(entityName: "Goal")
    do {
        allGoals = try context.fetch(requestGoal) as! [NSManagedObject]
      print("loadTasks() fired!")
    } catch let error as NSError {
      print("Could not fetch. \(error), \(error.userInfo)")
    }
}

I think the issue lies in the Transformable goalTasks attribute in Goal Entity but I am not sure what to do with it. any help is appreciated!

2
You shouldn't store NSManagedObjects (or subclasses) as transformable attributes - you should use relationships. But you have that as well (tasks). Why do you need the goalTasks attribute? - pbasdf
i want to store an array of tasks object in my goal. because the goal entity has an array of subtasks in order to achieve the goal something like that - CharlesLenx
How is that different from the tasks relationship, which represents the tasks that are related to the goal? - pbasdf
I understand, then how do I assign certain tasks to certain goals? - CharlesLenx

2 Answers

0
votes

The error arises because you have specified the goalTasks attribute to be Transformable with custom class [NSManagedObject]. When you fetch the Goals, CoreData uses the default value transformer to create an array of objects, which results in it calling the initWithCoder method of your Tasks class. Since that method doesn't exist, you get the crash.

However, you do not need to use the goalTasks attribute: you have a tasks relationship defined. To assign certain Tasks to certain Goals, you use the methods identified in the corresponding class definitions, eg. addToTasks and addToGoals, ie:

certainGoal.addToTasks(certainTask)

or

certainTask.addToGoals(certainGoal)

Note you need only use one of these methods. Because the relationships are defined as inverses, CoreData will automatically update the inverse.

0
votes

@pbasdf answer is correct but has a limitation

cause of the goals are unique you cant add goals twice or more with a relationship. in this case you have to add an intermediate entity which will hold the goals

in my case:

i have an app in which you have to go from start to 2 waypoints and back to start

the problem here ist to add the start-waypoint at last position

this does not work with pbasdf answer... cause you cant add them twice or more