swiftstringcore-datansmanagedobjectnsentitydescription

CoreData: Converting a String into an NSManagedObject instance


I've been working with CoreData for one of my iOS apps and wanted to build a helper function to turn a String representation of a CoreData entity into an NSManagedObject instance of that entity. I've just finished my first Swift course for my major and from my understanding, I assume the logic/implementation is fairly simple. I believe my implementation is wrong because Swift is my newest programming language. I'm trying to avoid hard-coding a solution because my intuition tells me there's a better, more general way to achieve my goal.

Example (Naïve Pseudocode):

func getEntity(from string: String) -> NSManagedObject {
    return string as! NSManagedObject
}

Desired Execution:

let stringRep = "Entity"
entity(from: stringRep)

Entity

Context:

Two of the CoreData entities I'm working with are Category and Service.

public class Category: NSManagedObject { }
public class Service: NSManagedObject { }

Category contains a relationship to many Service entities and my other helper functions in AppService access CoreData using that relationship.

CategoryTableViewController has three static cells, each containing a String representation of the entities for Category.

I'm passing the selected String representation of an entity such as Service during prepare(for segue: UIStoryboardSegue, sender: Any?) to the next UIViewController with a UITableView.

Using the new helper function, I will be able to ambiguously fetch from CoreData with the String representation and display the data in the UITableView.

My ultimate goal is to cut out unnecessary functions in AppService with the function below.

func get(_ entities: String, for category: Category) -> NSFetchedResultsController<T> {
    let someEntity = getEntity(from: entities)
    let fetchRequest: NSFetchRequest<someEntity> = someEntity.fetchRequest()
    fetchRequest.predicate = NSPredicate(format: "category == %@", category)
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]

    return createFetchedResultsController(for: fetchRequest)
}

Example:

get("Service", for: category)

Solution

  • You can create a new object of a certain entity based on the entity name. As always, you will need your managed object context.

    First you have to get the NSEntityDescription:

    let entity = NSEntityDescription.entity(forEntityName: "Widget", in: context)
    

    Then you can create the object:

    let newWidget = NSManagedObject(entity: entity, in: context)
    

    However, it would be much better to use the subclass. It includes the entity information automatically.

    let newWidget = Widget(context: context)  // much easier