1

I'm using Swift 3, Core Data, and a NSFetchedResultsController, and I'm forced to do the following:

let fetchRequest = Project.fetchRequest() as! NSFetchRequest<Project>

Why can't I just write let fetchRequest = Project.fetchRequest()? I see that Project.fetchRequest returns a NSFetchRequest<NSFetchRequestResult>, but shouldn't it be able to infer NSFetchRequest<Project> since I'm using the Project entity?

Of course, I could write

let fetchRequest = NSFetchRequest<Project>(entityName: "Project")

but I would like to avoid the use of strings for the entity name. Thanks for any help!

eirikvaa
  • 1,070
  • 1
  • 13
  • 24
  • See http://stackoverflow.com/questions/37810967/how-to-apply-the-type-to-a-nsfetchrequest-instance. – Martin R Nov 22 '16 at 21:51
  • I saw that post, and in both cases it forced me to cast it to `NSFetchRequest`. I find this very strange, but I guess I'll have to live with it. Thanks for the help. – eirikvaa Nov 22 '16 at 22:01

2 Answers2

1

In NSManagedObject there is a method:

class func fetchRequest() -> NSFetchRequest<NSFetchRequestResult>

If you use automatic code generation for model objects, then each generated class will have a method:

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

For example if you have the following hierarchy of models:

Animal
- Cat
- Dog

Then XCode will generate the following methods:

// for Animal model object
@nonobjc public class func fetchRequest() -> NSFetchRequest<Animal> {
   return NSFetchRequest<Animal>(entityName: "Animal")
}

// for Cat model object
@nonobjc public class func fetchRequest() -> NSFetchRequest<Cat> {
   return NSFetchRequest<Cat>(entityName: "Cat")
}

// for Dog model object
@nonobjc public class func fetchRequest() -> NSFetchRequest<Dog> {
   return NSFetchRequest<Dog>(entityName: "Dog")
}

In this case, when you write Cat.fetchRequest() the compiler does not know which of the 3 overloads to choose.

  1. This request will return all animals, cats, and dogs:
let request: NSFetchRequest<Animal> = Cat.fetchRequest()
  1. This request will return only cats:
let request: NSFetchRequest<Cat> = Cat.fetchRequest()
  1. And this query will return all the animals, cats and dogs, but the result will not be typed:
let request: NSFetchRequest<NSFetchRequestResult> = Cat.fetchRequest()
dronpopdev
  • 797
  • 10
  • 13
0

Short answer: If you use standard generated classes for your Core Data entities, use this:

let request: NSFetchRequest<MyEntity> = MyEntity.fetchRequest()

You must cast the NSFetchRequest object to a specific entity class, otherwise Swift doesn't know the result type of the request.

Ely
  • 8,259
  • 1
  • 54
  • 67