How to use predicates with fetchRequest in Core Data

31,113

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")
}
Share:
31,113
vrao
Author by

vrao

woking on a green energy app

Updated on March 31, 2021

Comments

  • vrao
    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
    vrao over 7 years
    I get error Contact on this line: "Ambiguoius use of fetchrequest". let fetchRequest = Contact.fetchRequest()
  • vrao
    vrao over 7 years
    Changed 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
    vadian over 7 years
    I was assuming that you're using a NSManagedObject subclass because providerName is accessed with dot notation. The subclass must contain the method fetchRequest(). I updated the answer.
  • vrao
    vrao over 7 years
    Yes 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
    vadian over 7 years
    A 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
    Soheil Novinfard about 6 years
    full of typo mistakes
  • vadian
    vadian about 6 years
    @SoheilNovinfard Thanks for pointing out. I updated the answer.