How to use predicates with fetchRequest in Core Data
First of all get rid of all NSString
and NSDictionary
occurrences. This is Swift!. Use the Swift native structs String
and Dictionary
.
Second of all put always all good code in the do
scope of a do - catch
block.
A CoreData predicate has a simple format attribute == value
which is very similar to aContact.uniqueId! == contactIdentifierString
:
var contactIdentifierString = ""
func userSelectedContact(contactIdentifier: String) {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
let fetchRequest : NSFetchRequest<Contact> = Contact.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "uniqueId == %@", contactIdentifier)
let fetchedResults = try context.fetch(fetchRequest)
if let aContact = fetchedResults.first {
providerName.text = aContact.providerName
}
}
catch {
print ("fetch task failed", error)
}
}
The code assumes that there is a NSManagedObject
subclass Contact
containing
@nonobjc public class func fetchRequest() -> NSFetchRequest<Contact> {
return NSFetchRequest<Contact>(entityName: "Contact")
}
Comments
-
vrao about 3 years
I pass a contact Identifier from Contacts tableview controller to another Location tableview controller. So I define a delegate ContactSelectionDelegate and implement method userSelectedContact in Location tableview controller and get contactIdentifierString
I am searching the database to find a match for contactIdentifierString and find value for another attribute provider name. This involves searching the whole database. Is there a faster way by assigning a predicate to the context fetchRequest. I thought that would be faster and fewer lines of code.
Can someone suggest how to use predicates with contact fetchRequest?
ContactTableViewController code:
protocol ContactSelectionDelegate{ func userSelectedContact(contactIdentifier:NSString) } class ContactTableViewController: UITableViewController { var delegate:ContactSelectionDelegate? = nil override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if (delegate != nil){ let contactDict:NSDictionary = allContacts.object(at: indexPath.row) as! NSDictionary let identifier = contactDict.object(forKey: "uniqueId") delegate!.userSelectedContact(contactIdentifier: identifier as! NSString) self.navigationController!.popViewController(animated: true) } }
}
LocationTableViewController code:
class LocationTableViewController: UITableViewController, ContactSelectionDelegate, CLLocationManagerDelegate { var contactIdentifierString:NSString = NSString() func userSelectedContact(contactIdentifier: NSString) { var fetchedResults: [Contact] = [] let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext do { fetchedResults = try context.fetch(Contact.fetchRequest()) } catch { print ("fetch task failed") } if fetchedResults.count > 0 { for contact in fetchedResults{ let aContact:Contact = contact if (aContact.uniqueId! == contactIdentifierString as String) { providerName.text = aContact.providerName } else { continue } } } }
-
vrao over 7 yearsI get error Contact on this line: "Ambiguoius use of fetchrequest". let fetchRequest = Contact.fetchRequest()
-
vrao over 7 yearsChanged it to : let req:NSFetchRequest<Contact> = Contact.fetchRequest(). Now I get error: Use of undeclared type NSFetchRequest. Looks like I don’t have NSManagedObject subclasses. So Generated NSManagedObject subclasses for both my entities. I get error on my Contact entity inside Contact+CoreDataProperties.swift as “Contact is ambiguous for type lookup in this context”. May be the NSManagedObject classes got autogenerated. Circling with errors. Can you pl. explain and how to fix?
-
vadian over 7 yearsI was assuming that you're using a NSManagedObject subclass because
providerName
is accessed with dot notation. The subclass must contain the methodfetchRequest()
. I updated the answer. -
vrao over 7 yearsYes it works. Can you explain what is fetchedResults.first.? I am going to accept your solution as answer. But I thought If I accept you may not be able to reply my question. But I will accept it
-
vadian over 7 yearsA CoreData fetch returns always an array and this kind of fetch request is supposed to return only one item on success. The line
if let .... .first
gets the first item in the array if the array is not empty (first
returns an optional). -
Soheil Novinfard about 6 yearsfull of typo mistakes
-
vadian about 6 years@SoheilNovinfard Thanks for pointing out. I updated the answer.