Is it possible to exclude the object with the latest date? - ios

I have a Core Data Model with an Entity that has an attribute "creation Date"
What I'd like to do is to create a fetch request that has all objects but not the latest.
As the content of the Core Data store changes while the user looks at the data (i.e. a UITableView) I can not set a "latest Object" and use this for the NSPredicate.
So is there a way to create a format to exclude the data set with the latest date?

Yes, you can build your NSFetchRequest with the following settings:
Sort by date, descending order
Set the offset to 1
execute the fetch and it will skip the first record.
You can then load it into a NSFetchedResultsController if appropriate.

If you are displaying the results in a table view, you can manipulate the datasource to omit the last result. (You return count minus one in numberOfRowsInSection.) This should work perfectly well with a fetched results controller as well. Don't forget to also modify the delegate methods.
If you just need an array (not recommended), read into a mutable array and remove the first or last object (depending on sort order). When the data changes, just re-fetch and replace the array.

Related

Search for the index of a Core Data array that contains a certain date attribute

I have been looking around everywhere online and can't seem to get a solid answer. If I have an event with multiple attributes stored in Core Data in an array and I can display all of these individual events in a tableView. Lets say one of the attributes is a date. Is there away to search for all of the events that contain a certain date and display only those in the tableView? I was thinking of using NSPredicate from what I am seeing online but I am not familiar with this. Maybe somehow find the index of the event that contains that date and only display that index? Any ideas?
Table views are designed to implement a one to one relationship with the underlying array of data. The usual approach is to use a fetchRequest to only get the data you want to display ( I personally like to have all my requests pre-defined in the data model so I can keep track of how data is accessed).
But, if your array of managed record must contain more elements than what you want to display, you should consider basing your tableView datasource responses on an intermediate array that only contains (or refers to) the objects you want to show.
For example:
let allEvents:[EventRecord] = GetAllEvents()
var filteredEvents:[EventRecord] = allEvents.filter({ $0.eventDate.isEqualToDate(dateToDisplay) })
and use filteredEvents as your underlying store for your datasource.
This will make it easy to dynamically change the filtering conditions and reload the tableview without having to go back to the database for each filter change.

Filter NSFetchedResultsController request with predicate using computed attribute? [duplicate]

Is there a way to use a 'transient' field or something like that and in some way sort accordingly with a NSFetchedResultsController. I want to do the following:
I have location of places in a database. When a person opens the list, I want to show the nearest place on top, an then sort accordingly to distance. But clearly,this depends on the users location, so I cannot use a static field. I was hoping to use a transient field, as you can use for the section headers.
Is there anybody who can give a solution or workaround for this situation?
You cannot use a transient property in a fetch request for a SQlite base Core Data store.
See Fetching Managed Objects in the "Core Data Programming Guide":
You cannot fetch using a predicate based on transient properties
(although you can use transient properties to filter in memory
yourself). ... To summarize, though, if you execute a fetch directly, you should
typically not add Objective-C-based predicates or sort descriptors to
the fetch request. Instead you should apply these to the results of
the fetch.
You can use a transient property for sectionNameKeyPath, but even then you need a first sort descriptor for the sections that is based on a persistent attribute.
So the only workaround is probably to fetch all objects and then sort the fetched array. But then of course you don't have the advantages of a fetched results controller anymore.

CoreData doesn't keep the sequence while saveContext

I am trying to insert data in CoreData. I have may records to insert, this should be all or none. So I am creating instance of NSManagedObject and inserting it to NSManagedObjectContext one by one.
When I call below method after inserting all records:
[_myManagedObjectContext saveContext:&error];
This method save all inserted records to persistent store. When I open the Sqlite file generated by core data, I found all the records inserted by my app.
Problem is the order is not same. e.g I inserted records based on serial number 1-100 in sequense, I am able to see random sequence in CoreData sqlite file.
I know that I should not worry about the entries on core data sqlite file I can always fetch records in sorted order using NSPredicate but I need to keep the sequence because in some circumstances I need to study the database file.
Can someone tell me what to do to let saveContext method save records in the same order those are inserted to context?
The only way to reliably maintain order of your objects is to add an additional attribute on the object, such as 'index', and then set the value once the object has been created. Use this object to sort the results when you retrieve them or use the index to retrieve the objects in the required order.
The easiest way is to implement the NSManagedObject subclass's awakeFromInsert method and set a date property to NSDate(). Now you have a sequence which is accurate to 10,000th of a second. When you need items in order, just sort by this date property.

FetchResultsController sorting issue

I have an NSFetchResultsController initialised with an NSSortDescriptor that sorts according to the localizedCaseInsensitiveCompare: method.
Entities are sorted on their last name, however some of them don't specify their last name and hence, the char 170 (in ASCII) is set as their last name (don't ask me why, the source code is done that way and I rather don't change it). When sorted, these persons "without last name" are displayed at the top of the table view. I would like them to be at the end of it.
Seems that it is not possible to use specific NSSortDescriptor in my case (i'm using a FRC), what are my options here ?
[EDIT]
Comparator blocks or custom comparator methods won't work with NSFetchResultsController
Your options are limited as the sort descriptor needs to be able to work with an SQLite data store.
You should edit the data model so you have an attribute that you can sort on. Exactly how you calculate the value is up to you, but the attribute can't be temporary. I would suggest that you either:
Implement willSave in your NSManagedObject subclass to create / update the sort data
Or, make your sort data a dependent key (using KVO, again in your NSManagedObject subclass)
Your sort data could be as simple as:
self.sortValue = (self.lastName == 170 in ASCII ? #"ZZZZZZZZZZZZZZZ" : lastName)

Insert extra row into UITableView like Tweetbot iOS

I have NSFetchedResultsController like datasource of my UITableView. It displays some entities with predicate from my database. I try to find an elegant solution to insert utility row between my data rows. I don't want to create fake entity in my database cause I don't want to mix View and Model. But I need to have ability to recreate this utility row (e.g. on other application launch). Any suggestions?
It should look something like this:
You're best bet, in my opinion, is to use a section header or footer for that "utility" row. In the case of Tweetbot, they're most likely caching results locally and then merge in data when the plus button is tapped. Your table will take multiple data sets as arrays (an array of arrays) and treat each separate array as a chunk and put it into its own section.
Any way you implement you'll want to wrap your results from the database with some sort of metadata. I think you're going to have to get away from a fetched results controller, unless you use a separate instance for each chunk, keeping track of the date range for each chunk.

Resources