Reputation: 397
In an earlier version of swift, I had a core data function
func retrieveItemsForRelatedEntity(entity: String, relatedEntity: String, identifier: String, sortDescriptors: [NSSortDescriptor]?) -> Array<AnyObject>? {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let frequest = NSFetchRequest(entityName: entity)
frequest.returnsObjectsAsFaults = false
if sortDescriptors != nil {
frequest.sortDescriptors = sortDescriptors
}
switch relatedEntity {
case "CostCentre":
frequest.predicate = NSPredicate(format: "costCentre.identifier == '\(identifier)'")
return try! context.executeFetchRequest(frequest)
case "CostCentreDay":
frequest.predicate = NSPredicate(format: "costCentreDay.identifier == '\(identifier)'")
return try! context.executeFetchRequest(frequest)
case "Resource":
frequest.predicate = NSPredicate(format: "resource.identifier == '\(identifier)'")
return try! context.executeFetchRequest(frequest)
case "ResourceDay":
frequest.predicate = NSPredicate(format: "resourceDay.identifier == '\(identifier)'")
return try! context.executeFetchRequest(frequest)
case "CostedDay":
frequest.predicate = NSPredicate(format: "costedDay.identifier == '\(identifier)'")
return try! context.executeFetchRequest(frequest)
default:
print("wrong entity for this function")
return nil
}
}
With Swift 3.0, the "Generic Result Type cannot be inferred", so instead of passing in the entity title Strings, can I pass in the entity Type, and switch on that for my fetch request?
Upvotes: 1
Views: 1285
Reputation: 576
please try this. It helped me.
func retrieveItemsForRelatedEntity(entity: String, relatedEntity: NSEntityDescription, identifier: String, sortDescriptors: [NSSortDescriptor]?) -> Array<AnyObject>? {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.persistentContainer.viewContext
let frequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
and
switch relatedEntity {
case NSEntityDescription.entity(forEntityName: "CostCentre", in: context)!:
Upvotes: 2
Reputation: 8411
To answer your question
so instead of passing in the entity title Strings, can I pass in the entity Type, and switch on that for my fetch request?
Yes, that would be the best approach. Something like
retrieveItemsForRelatedEntity(entity: NSManagedObject, relatedEntity: String, identifier: String, sortDescriptors: [NSSortDescriptor]?) -> Array<AnyObject>? {
You have to specify the generic type because otherwise the method call is ambiguous.
The first version is defined for NSManagedObject, the second version is generated automatically for every object using an extension, e.g:
This extension is automatically generated (as can be seen below with the Animal
type.
From Apple's Documentation on changes from Swift 2
to Swift 3
NSFetchRequest is now a parameterized type based on a new NSFetchRequestResult protocol.
The function name for executeFetchRequest(...)
also changed in Swift 3
public func fetch<T : NSFetchRequestResult>(_ request: NSFetchRequest<T>) throws -> [T]
Apple Documentation example of changes to NSFetchRequest
Swift 2
func findAnimals() {
let request = NSFetchRequest(entityName:”Animal")
do {
guard let searchResults = try context.executeFetchRequest(request) as? [Animal] else {
print("Results were not of the expected structure")
}
... use(searchResults) ...
} catch {
print("Error ocurred during execution: \(error)")
}
}
Swift 3
func findAnimals() {
let request: NSFetchRequest<Animal> = Animal.fetchRequest
do {
let searchResults = try context.fetch(request)
... use(searchResults) ...
} catch {
print("Error with request: \(error)")
}
}
So converting your code in Swift 2 for creating NSFetchRequest
let frequest = NSFetchRequest(entityName: entity)
to Swift 3
let frequest: NSFetchRequest<YourEntityType> = YourEntityType.fetchRequest()
and
context.executeFetchRequest(frequest)
will be
context.fetch(frequest)
Note: From other examples across the web the Apple docs code example of Animal.fetchRequest
may be wrong and instead should be Animal.fetchRequest()
Upvotes: 2
Reputation: 6892
Try this :
let frequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
Upvotes: 1