NSFetchRequest ReturnsDistinctResults gives empty results - swift

I am trying to filter out the duplicate items in a result from a fetchRequest. I use the following code:
let sortDescriptor = NSSortDescriptor(key: "lastupdate", ascending: false)
let sortDescriptors = [sortDescriptor]
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let fetchRequest = NSFetchRequest(entityName:"Details")
fetchRequest.sortDescriptors = sortDescriptors
fetchRequest.propertiesToFetch = [ "orig_id" ]
fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType
fetchRequest.returnsDistinctResults = true
let company_temp = try context.executeFetchRequest(fetchRequest)
let company = company_temp as! [Details]
for t in company {
let id = t.orig_id
print(id)
self.myarray.append("\(id)")
}
When I comment out these 3 lines:
fetchRequest.propertiesToFetch = [ "orig_id" ]
fetchRequest.resultType = NSFetchRequestResultType.DictionaryResultType
fetchRequest.returnsDistinctResults = true
I get 8 items in my array. What is wrong with my code?

Did you save your context?
I had the same problem. When you have unsaved changes, the NSDictionaryResultType does not reflect the current state of the persistent store. See Apple Docs about the includesPendingChanges: method.
So a simple context.save() before your code might fixes your problem.
Another problem is that this line will crash: let company = company_temp as! [Details] since you'll get a Dictionary back. Not a list of NSManagedObject.

Related

Swift sort FetchRequest result by Turkish locale

How can I sort fetchResult by Turkish language, turkish characters sorted at the end of results.
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let fetch = NSFetchRequest<Contact>(entityName: "Contact")
let sortDescriptor = NSSortDescriptor(key: "firstName", ascending: true)
let sortDescriptors = [sortDescriptor]
fetch.sortDescriptors = sortDescriptors
do {
let list = try managedObjectContext.fetch(fetch)
} catch {
fatalError("Failed \(error)")
}
Working code:
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
let fetch = NSFetchRequest<Contact>(entityName: "Contact")
let sortDescriptor = NSSortDescriptor(key: "firstName", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare))
let sortDescriptors = [sortDescriptor]
fetch.sortDescriptors = sortDescriptors
do {
let list = try managedObjectContext.fetch(fetch)
} catch {
fatalError("Failed \(error)")
}

Sort by date - Swift 3

I have a func getData() which retrieves core data entity, and I want to sort them by date. How can I apply NSPredicate or Predicate to get the data from CoreData sorted by date?
My core data entity:
Entity: Expenses
Attributes:
amount
category
date
func getData() {
let context = appDelegate.persistentContainer.viewContext
do {
expenses = try context.fetch(Expenses.fetchRequest())
} catch {
print("Cannot fetch Expenses")
}
}
Predicates are for filtering your search results. To sort them you need to use an NSSortDescriptor. Assuming you have an attribute on your Expenses entity called date of type Date:
func getData() {
let context = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<Expenses>(entityName: "Expenses")
let sort = NSSortDescriptor(key: #keyPath(Expenses.date), ascending: true)
fetchRequest.sortDescriptors = [sort]
do {
expenses = try context.fetch(fetchRequest)
} catch {
print("Cannot fetch Expenses")
}
}
EDIT: I should have mentioned that the sort selector is added in an array so that multiple sort descriptors can be added if needed. e.g. sort first by date, then by number of legs, then by volume, etc.
You need a sort descriptor to get all the objects in a specific order.
let sectionSortDescriptor = NSSortDescriptor(key: "date", ascending: true)
let sortDescriptors = [sectionSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
My function to do a fetchRequest of data in Core Data and sort the results by date "timestamp" in descending order. "Ruta" is the name of the entity.
//Array of Ruta entity
rutas = [Ruta]()
func getData() {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Ruta")
let sort = NSSortDescriptor(key: "timestamp", ascending: false)
request.sortDescriptors = [sort]
do {
rutas = try context.fetch(request) as! [Ruta]
} catch {
print("Fetching Failed")
}
}
In swift 4 or swift 5, you can use like
func sortlist(){
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "User")
let sort = NSSortDescriptor(key: "date", ascending: false)
fetchRequest.sortDescriptors = [sort]
//3
do {
let langugeCodes = try managedContext.fetch(fetchRequest)
for result in langugeCodes as [NSManagedObject] {
var username:String = result.value(forKey: "username")! as! String
print("username==>",username)
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
To get data which are lastly added at first, need to set key of sort descriptor as ObjectId.
let sectionSortDescriptor = NSSortDescriptor(key: #keyPath(Entity.ObjectId)
ascending: false) fetchRequest.sortDescriptors = [sectionSortDescriptor]

swift code core data fetchrequest

I'm going crazy trying to retrieve a fact for a given question in Core data. The code I'm using is below and what I'd like to do is let the user select a "question" and see the related "facts" for it.
I'm going around in circles trying to do this. Can anyone explain to me what I'm missing? Thank you
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "BadHusband")
request.predicate = NSPredicate(format: "question= %#", itemSelected)
request.returnsObjectsAsFaults = false
do {
let results = try managedContext.fetch(request)
stuff = results as! [NSManagedObject]
if results.count > 0 {
for result in results as! [NSManagedObject] {
if let question = result.value(forKey: "question"), let facts = result.value(forKey: "facts") {
print(question)
print(facts)
}
}
}

Core Data - How can I get the max value from an entity attribute (Swift)

Recipe
recipeID: Int
recipeName: String
I have an entity Recipe with an attribute recipeID.
How can I get the max(recipeID) as an Int value in Swift?
I'm new in swift, please help me.
Thanks in advance.
func fetchMaxID() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "recipeID", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let maxID = try [managedObjectContext?.executeFetchRequest(fetchRequest)].first
print(maxID)
} catch _ {
}
}
The way that Apple recommends and is the fastest is using NSExpressions. moc is a NSManagedObjectContext.
private func getLastContactSyncTimestamp() -> Int64? {
let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest()
request.entity = NSEntityDescription.entity(forEntityName: "Contact", in: self.moc)
request.resultType = NSFetchRequestResultType.dictionaryResultType
let keypathExpression = NSExpression(forKeyPath: "timestamp")
let maxExpression = NSExpression(forFunction: "max:", arguments: [keypathExpression])
let key = "maxTimestamp"
let expressionDescription = NSExpressionDescription()
expressionDescription.name = key
expressionDescription.expression = maxExpression
expressionDescription.expressionResultType = .integer64AttributeType
request.propertiesToFetch = [expressionDescription]
var maxTimestamp: Int64? = nil
do {
if let result = try self.moc.fetch(request) as? [[String: Int64]], let dict = result.first {
maxTimestamp = dict[key]
}
} catch {
assertionFailure("Failed to fetch max timestamp with error = \(error)")
return nil
}
return maxTimestamp
}
Learning from Ray Wenderlich's Core Data Tutorial
https://www.raywenderlich.com/115695/getting-started-with-core-data-tutorial/
func fetchMaxRecipe() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "recipeID", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let recipes = try context.executeFetchRequest(fetchRequest) as! [Recipe]
let max = recipes.first
print(max?.valueForKey("recipeID") as! Int)
} catch _ {
}
}
Hope this helps =).
func fetchMaxID() {
let context = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.fetchLimit = 1
let sortDescriptor = NSSortDescriptor(key: "recipeID", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let results = try context.executeFetchRequest(fetchRequest) as! [Recipe]
if (results.count > 0) {
for result in results {
print(result.recipeID!)
}
} else {
print("No Recipe")
}
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
This works also!
To check the max of an entity attribute you can simply use:
func findMaxRecipeID() -> Int {
let maxRecipeID = recipe?.value(forKeyPath: "recipe.#max.recipeID") as! Int
return maxRecipeID
}
You can use this to #sum, #max, #min, #count - saves quite a few lines of code.

Get last inserted item from Core Data, iOS

is there a way to get the last inserted item in a core data database?
This returns the very last inserted object.
setFetchLimit:1 and setFetchOffset:[number of all entries - 1]
Method 1:
I've extended #Olsi answer with sample code including the line to get number of all entities. Here's how I've done it:
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.managedObjectContext
let request = NSFetchRequest(entityName: "MyEntity")
let allElementsCount = context.countForFetchRequest(request, error: nil)
request.fetchLimit = 1
request.fetchOffset = allElementsCount - 1
request.returnsObjectsAsFaults = false
Method 2:
Howerver there's another approach using sortDescriptors. Not sure which is better fit, they both do the same job:
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = appDelegate.managedObjectContext
let request = NSFetchRequest(entityName: "MyEntity")
request.sortDescriptors = [NSSortDescriptor(key: "momentTimeStamp", ascending: false)]
request.fetchLimit = 1
request.returnsObjectsAsFaults = false
I don't think this is supported natively by Core Data. I guess your best bet is to add a "dateInserted" attribute to your entity.