5

how I can call es request with distinct values in swift?

This is my code:

let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let context: NSManagedObjectContext = appDelegate.managedObjectContext

    let request = NSFetchRequest(entityName: "MedicalData")
    request.propertiesToFetch = NSArray(object: "docID")
    request.returnsObjectsAsFaults = false
    request.returnsDistinctResults = true

    var results:NSArray = context.executeFetchRequest(request, error: nil)

    for data in results {
        var thisData = data as MedicalData
        println(thisData.docID)
    }

I want to get distinct values for "docID" but I get all of the entity :(

Thank your for help!

Maxim
  • 317
  • 1
  • 5
  • 13

3 Answers3

7

You need to set

request.resultType = NSFetchRequestResultType.DictionaryResultType

It returns dictionaries, but the distinct filter should work.

If you do not want to go down that route, filter in memory (also recommended). Do a normal fetch and then

let distinct = NSSet(array: results.valueForKeyPath("docID") as [String])

With Swift 2.0 I prefer

let distinct = NSSet(array: results.map { $0.docID })
Mundi
  • 79,884
  • 17
  • 117
  • 140
  • 3
    I'd actually recommend against the approach of fetching all results and then piping them through an NSSet as it does just that, fetch and instantiate all objects, just to throw some of them away. Far better to fix the approach he's currently taking by setting the resultType as that will do all of the filtering at the sqlite level and instantiate far fewer objects. Even more so if docID is indexed. – David Berry Jun 26 '14 at 18:37
  • 1
    True in principle, but the other method is simpler if there is not too much data. Even then, Core Data optimises for memory usage, so one should not necessarily assume that all the attributes are also fetched. – Mundi Jun 26 '14 at 19:32
5

As already mentioned the key is using

fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType

and

fetchRequest.propertiesToFetch = ["propertyName"]

both are required for distinct to work

fetchRequest.returnsDistinctResults = true

The next step is to deal with the results as Swift Dictionaries and returning the wanted values.

let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
    let managedContext = appDelegate.managedObjectContext!
    //FetchRequest
    let fetchRequest = NSFetchRequest(entityName: "Purchase")
    fetchRequest.propertiesToFetch = ["year"]
    fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType
    fetchRequest.returnsDistinctResults = true
    //Fetch
    var error: NSError?
    if let results = managedContext.executeFetchRequest(fetchRequest, error: &error)  {
        var stringResultsArray: [String] = []
        for var i = 0; i < results.count; i++ {
            if let dic = (results[i] as? [String : String]){
                if let yearString = dic["year"]?{
                    stringResultsArray.append(yearString)
                }
            }
        }
        return stringResultsArray
    }else {
        println("fetch failed: \(error?.localizedDescription)")
    }
    return []
Yedy
  • 2,107
  • 1
  • 25
  • 30
  • fetchRequest.returnsDistinctResults = true not working – AyAz Jun 04 '16 at 05:55
  • can we use predicate along with this ? – binaryKarmic Oct 24 '16 at 09:57
  • adding on @Yedy answer, using a `FetchedResultsController`simplify everything. If you need to populate a `TableView`with results check my answer as i put together a step-by-step guide of mandatory steps to follow. https://stackoverflow.com/questions/56168119/removing-duplicate-objects-from-fetch-based-on-object-parameter-updated-swift/56206126#56206126 – Vincenzo May 19 '19 at 08:54
-3

NSPredicate will allow you to search for specific values and retrieve only the data you need from core data:

  var StoredResults = [NSManagedObject]()

  func fetchRequest(docID : String ){

        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        let managedContext = appDelegate.managedObjectContext
        let request = NSFetchRequest(entityName: "EntityContainingDocID")

        let predicate =  NSPredicate(format:"docID == %@", docID)
        request.predicate = predicate

    do {
        let results =
        try managedContext.executeFetchRequest(request)

        StoredResults = results as! [NSManagedObject]

        } catch let error as NSError {
              print(" error executing fetchrequest  ", error)
        }
    }

In this example we are only looking to return specific values matching a string in the "docID" column but NSPredicate is a handy way of building SQL-like queries into your code and is pretty flexible.

NiallJG
  • 1,881
  • 19
  • 22