I am using coredata and I want to find maximum time in coredata.
How do I write?
let predicate = NSPredicate(format: "contentDate = '???' ", "")
fetchRequest.predicate = predicate
As Wain said, to find maximum value you rather have to define SortDescriptor then Predicate:
let sortByTimeDescriptor = NSSortDescriptor(key: "time", ascending: false)
fetchRequest.sortDescriptors = [sortByTimeDescriptor]
You are interested just in the one (maximum) value so it's also good practice to set fetch limit for performance reason:
fetchRequest.fetchLimit = 1
Then just execute request and get first object from results array:
let results = managedObjectContext.executeFetchRequest(fetchRequest)
let maxTimeEntity = results.first
Notice that executeFetchRequest can throw and error and you have to handle it somehow.
To find a maximum it makes more sense to sort and ask for the first item than to try to create a predicate.
You can also look at an expression using #max to get the value back on its own if the container object isn't important.
Related
I'm fetching objects from a Core Data database for an iOS app that have multiple properties, and on my 3rd of the sort keys, I want to sort on Job Title, alphabetically ascending, but with the twist that "Chair" (i.e. the position of Department Chairman) sorts ahead of all other job titles (even those that are alphabetically ahead of it). The code I have below attempts to use the third sort descriptor to sort "Chair" above all other faculty positions using a Boolean, and then the 4th sort descriptor ranks all positions (i.e. sorting among all the job titles besides "Chair") alphabetically.
As is, I get an error on that third descriptor, having tried various permutations of the syntax that I can think of.
If I comment out that third descriptor, everything works & I get good results, other than the job title of Chairman falls in alphabetical order (so "Adjunct" then "Chair" then "Emeritus" and etc). What I want is -- after the first and second sorting keys have been applied -- for job titles to sort "Chair" first and then "Ajunct", "Emeritus", etc.
How should I be coding that third sort descriptor to make that happen?
I suspect that this question or this question may accomplish this, but the answers to both of those are in Objective C, and I'm not able to follow that enough to see how I'd convert either of those solutions to Swift.
func allProjects() -> [Projects] {
// fetches the array of Projects from Core Data & returns it.
do {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Projects")
// Order that I want to sort:
// 1 First by Month/Year (expressed as an Int32, 201803 = March 2018, for instance
// 2 then by Department (Astrology then Biology then Chemistry then Economics then etc)
// 3 then by departmentPosition = “Chair” — put the Chairman’s project(s) first
// 4 then by departmentPosition — everybody ELSE in alpha order: Adjunct > Emeritus > Lecturer > etc
// 5 then by Industry Partner in alphabetical order
let sortDescript1 = NSSortDescriptor(key: "yearMonthInt", ascending: false)
let sortDescript2 = NSSortDescriptor(key: "department", ascending: true)
let sortDescript3 = NSSortDescriptor(key: "{departmentPosition == ‘Chair’}", ascending: false). // Problem is here
let sortDescript4 = NSSortDescriptor(key: "departmentPosition", ascending: true)
let sortDescript5 = NSSortDescriptor(key: "industryPartner", ascending: true)
fetchRequest.sortDescriptors = [sortDescript1, sortDescript2, sortDescript3, sortDescript4, sortDescript5]
do {
let fetched = try myContext.fetch(fetchRequest) as! [Projects]
return fetched
}
} catch {
fatalError("Couldn't fetch [Projects]: \(error)")
}
}
EDIT 1: An idea that doesn't quite work
It was suggested in a comment that the comparison needed to be
let sortDescript3 = NSSortDescriptor(key: "departmentPosition", ascending: true, comparator: myComparator)
The problem is, that also generates an error (CoreData: error: exception handling request: <NSSQLFetchRequestContext: 0x7b3400037e90> , unsupported NSSortDescriptor (comparator blocks are not supported)), and searching for the text of that error turns up this question/answer, which states that you can't use comparator blocks with Core Data.
So I have a simple shopping list. So far the list is being added alphabetically. When I do ascending false, it goes from Z-A and ascending true is from A-Z.
I just want the items to be added based on when they were added. No ordering, no nothing. It just adds to the back of the list.
Here is what I have so far:
func taskFetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Shopping")
let sortDescriptor = NSSortDescriptor(key: "item", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
To do this, you must add something like a date-added field to your Shopping object. Then you sort on that date-added value.
This is simply because database (including CoreData) tables don't have an intrinsic ordering. (Often the underlying database engine does generate id's that may seem to increment. But you should never rely on these internal values.)
You are sorting based on the name, I assume that's what item is in this line of code
let sortDescriptor = NSSortDescriptor(key: "item", ascending: false)
If you want to sort by something else, add a property called createdDate (or something) which you can initialise in the ManagedObject's awakeFromInsert method, and then you can use that as the sort key:
let sortDescriptor = NSSortDescriptor(key: "createDate", ascending: false)
Currently I have an application with core data that has a view controller which requires a specific sorting for the UITableView. An entity can have a event_name and assigned_time, along with other attributes. The basic idea is if an event is assigned to a more recent time, then that event will be shown first in the tableview.
What I want to know is what is the best way of sorting my information by assigned_time but group by event_name? I have tried using NSSortDescriptor with the section being assigned_time but I then just end up ordering by the name and not having the event with earlier times come first in the list.
Essentially I want to achieve something similar to how email threads work where entities with a more recent assigned_time coming in will push a section up the list hence why the section ordering depends on the time
My code for the NSFetchRequest is as follows:
func getFetchRequest() -> NSFetchRequest<NSFetchRequestResult> {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "EntitySet")
request.predicate = ...
let eventSort = NSSortDescriptor(key: "event_name", ascending: true)
let timeSort = NSSortDescriptor(key: "assigned_time", ascending: false)
request.sortDescriptors = [eventSort, timeSort]
return request
}
Try this :
var request : NSFetchRequest<NSFetchRequestResult>!
request.sortDescriptors = [NSSortDescriptor(key: "event_name", ascending: true), NSSortDescriptor(key: "assigned_time", ascending: true)]
request.propertiesToGroupBy = ["event_name"]
I have a core data entity that looks like this:
name: String
creationDate: Date
I would like to retrieve the last 5 unique names when ordered in descending order by creation date. What is the most efficient way to query this data from CoreData?
Both these solutions are efficient depending on the situation.
If you do not have memory constraints (i.e. not too many records) you could fetch all sorted by date, use KVC to filter and take the top n records.
(allItems as NSArray).valueForKeyPath("#distinctUnionOfSets.name")
If you like to fetch this directly from the store, you have to drop back to NSDictionaryResultType for your fetch request. Something like
let request = NSFetchRequest(entityName:"Item")
request.resultType = NSDictionaryResultType
request.returnsDistinctResults = true
let entity = NSEntityDescription(name: "Item", inManagedObjectContext: context)
let description = entity.propertiesByName["name"]
request.propertiesToFetch = [description!]
request.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
request.fetchLimit = 5
I have one to many relationship in my core data model ('Client'<-->>Assessment') and in my assessment tableview I am currently filtering assessments by client name.
func assessmentFetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Assessment")
let sortDescriptor = NSSortDescriptor(key: "nsDateOfAssessment", ascending: false)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format: "client.name == %#", self.client.name)
return fetchRequest
}
I would like to know how, or if its possible, to filter by the specific managed object instead of an attribute of the managed object ('name' in this case). I've tried changing my predicate to this:
fetchRequest.predicate = NSPredicate(format: "client.objectID == %#", self.client.objectID)
but I just get a crash with an uncaught exception.
I'm wanting to change this because it seems bad practice to filter by name since two clients may have the same name and therefore the same filter results.
So I am going to guess that for you sort descriptor the key name of 'nsDateOfAssessment' is not the actual name of the core data attribute. The key should be the actual name of attribute. Also, I wouldn't say that filtering by first name is bad practice. Perhaps add an additional param to your predicate that can help pinpoint the correct items. Of course, if you are storing a unique identifier for each entity, it would be a cleaner way to go about it.