How to apply a type to an instance of NSFetchRequest?

The following code worked in Swift 2:

let request = NSFetchRequest(entityName: String) 

but in Swift 3 it gives an error:

General parameter "ResultType" cannot be displayed

because NSFetchRequest now a generic type. In their docs they wrote this:

 let request: NSFetchRequest<Animal> = Animal.fetchRequest 

so if my class of results, for example, Level , how should I query correctly?

Because it does not work:

 let request: NSFetchRequest<Level> = Level.fetchRequest 
+85
swift swift3 core-data
Jun 14 '16 at 11:39
source share
8 answers
 let request: NSFetchRequest<NSFetchRequestResult> = Level.fetchRequest() 

or

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

depending on which version you want.

You must specify a generic type, because otherwise the method call is ambiguous.

The first version is defined for NSManagedObject , the second version is created automatically for each object using the extension, for example:

 extension Level { @nonobjc class func fetchRequest() -> NSFetchRequest<Level> { return NSFetchRequest<Level>(entityName: "Level"); } @NSManaged var timeStamp: NSDate? } 

The thing is to remove the use of string constants.

+113
Jun 14 '16 at 12:18
source share

I think I did it:

 let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level") 

at least it saves and loads data from the database.

But it seems that this is not the right solution, but it works for now.

+52
Jun 14 '16 at 12:14
source share

The simplest structure I found that works in version 3.0 is as follows:

 let request = NSFetchRequest<Country>(entityName: "Country") 

where the data object Type is the country.

However, when I tried to create a basic BatchDeleteRequest file, I found that this definition does not work, and it seems to you that you need to go to the form:
 let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest() 

although the formats ManagedObject and FetchRequestResult should be equivalent.

+32
Jun 15 '16 at 22:58
source share

This is the easiest way to upgrade to Swift 3.0, just add <Country>

(checked and processed)

 let request = NSFetchRequest<Country>(entityName: "Country") 
+6
Oct 19 '16 at 7:36
source share

Here are some common CoreData methods that can answer your question:

 import Foundation import Cocoa func addRecord<T: NSManagedObject>(_ type : T.Type) -> T { let entityName = T.description() let context = app.managedObjectContext let entity = NSEntityDescription.entity(forEntityName: entityName, in: context) let record = T(entity: entity!, insertInto: context) return record } func recordsInTable<T: NSManagedObject>(_ type : T.Type) -> Int { let recs = allRecords(T.self) return recs.count } func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T] { let context = app.managedObjectContext let request = T.fetchRequest() do { let results = try context.fetch(request) return results as! [T] } catch { print("Error with request: \(error)") return [] } } func query<T: NSManagedObject>(_ type : T.Type, search: NSPredicate?, sort: NSSortDescriptor? = nil, multiSort: [NSSortDescriptor]? = nil) -> [T] { let context = app.managedObjectContext let request = T.fetchRequest() if let predicate = search { request.predicate = predicate } if let sortDescriptors = multiSort { request.sortDescriptors = sortDescriptors } else if let sortDescriptor = sort { request.sortDescriptors = [sortDescriptor] } do { let results = try context.fetch(request) return results as! [T] } catch { print("Error with request: \(error)") return [] } } func deleteRecord(_ object: NSManagedObject) { let context = app.managedObjectContext context.delete(object) } func deleteRecords<T: NSManagedObject>(_ type : T.Type, search: NSPredicate? = nil) { let context = app.managedObjectContext let results = query(T.self, search: search) for record in results { context.delete(record) } } func saveDatabase() { let context = app.managedObjectContext do { try context.save() } catch { print("Error saving database: \(error)") } } 

Assuming you can set NSManagedObject for Contact:

 class Contact: NSManagedObject { @NSManaged var contactNo: Int @NSManaged var contactName: String } 

These methods can be used as follows:

 let name = "John Appleseed" let newContact = addRecord(Contact.self) newContact.contactNo = 1 newContact.contactName = name let contacts = query(Contact.self, search: NSPredicate(format: "contactName == %@", name)) for contact in contacts { print ("Contact name = \(contact.contactName), no = \(contact.contactNo)") } deleteRecords(Contact.self, search: NSPredicate(format: "contactName == %@", name)) recs = recordsInTable(Contact.self) print ("Contacts table has \(recs) records") saveDatabase() 
+5
Oct 15 '16 at 7:47
source share

I also had a "ResultType", there could be no error output. They cleared as soon as I rebuilt the data model, setting the value of "Class Definition" for each Codegen object. I made a brief entry with step-by-step instructions here:

Looking for a clear guide to the revised NSPsistentContainer in Xcode 8 with Swift 3

By "rebuilt", I mean that I created a new model file with new entries and attributes. A bit tiring, but it worked!

0
Sep 23 '16 at 4:02
source share

What worked best for me so far was:

 let request = Level.fetchRequest() as! NSFetchRequest<Level> 
0
Sep 30 '16 at 9:57
source share

I had the same problem and solved it with the following steps:

  • Select the xcdatamodeld file and go to the Data Model Inspector
  • Select your first object and go to the Class section.
  • Make sure Codegen Class Definition is selected.
  • Delete all the Entity files you created. You don’t need them anymore.

After that, I had to remove / rewrite all occurrences of fetchRequest, since Xcode seems to be somehow mixed with the encoded version.

NTN

0
Dec 23 '16 at 8:29
source share



All Articles