iphone coredata fetch-request sorting - iphone

I'm using core data and fetching the results successfully. I've few questions regarding core data
1. When I add a record, will it be added at the end or at the start of entity.
2. I'm using following code to fetch the data. Array is being populated with all the records. But they are not in the same order as I entered records into entity. why? on what basis default sorting is used?
NSFetchRequest* allLatest = [[NSFetchRequest alloc] init];
[allLatest setEntity:[NSEntityDescription entityForName:#"Latest" inManagedObjectContext:[self managedObjectContext]]];
NSError* error = nil;
NSArray* records = [managedObjectContext executeFetchRequest:allLatest error:&error];
[allLatest release];
3. The way that I enter the records, 1,2,3,4......... after some time, I want to delete the records that I entered first(i mean oldest data). Something like delete oldest two records. How to do it?

A sort on the array you have looks like this:
NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:#"SortKey" ascending:YES] autorelease];
NSArray *sortedList = [records sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor, nil]];
The initWithKey: argument is the property you would like to sort on. If you have multiple keys to sort on, they can be added to the sortedArrayUsingDescriptors: argument as a list. The list will be sorted by the first descriptor, then each group by the next descriptors.
-dan

Ordering is not guaranteed in any way. If you care about order, you need to include an attribute in your entity (for example, call it "sequenceNumber") and use that in a sort descriptor with your NSFetchRequest.

Related

How to get last inserted record from core database?

I am trying to fetch last inserted object from core database. But i did't find way to fetch last inserted object from database. Currently i am fetching all records from database in array and using last object of array for last inserted object.
But i want to fetch only single object from database.
Is there anyway to find a last single record from database.?
Thanks and regards
Sarabjit Singh
//=== Sort your record ======//
NSSortDescriptor *sorting = [[NSSortDescriptor alloc] initWithKey:#"timeStamp" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sorting]];
NSArray *fetchObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:nil];
NSMutableArray *lastIndex = [[NSMutableArray alloc]init];
[lastIndex addObject:[fetchObjects objectAtIndex:0]];
See this question: Get last inserted item from Core Data, iOS
The following is the key when running your fetch:
setFetchLimit:1 and setFetchOffset:[number of all entries - 1]

NSFetchResultController i am using predicate with attribute in array?

In NSFetchRsultController I am using:
[NSPredicate predicateWithFormat:#"type in %#", myArray];
I want the data in the order of the data in the array, but NSSortDescriptor is mandatory for the NSFetchResultController, so what NSSortDescriptor I have to use?
You can use sortDescriptors to order the data in order of your array.
The sort descriptors specify how the objects returned when the fetch request is issued should be ordered—for example by last name then by first name. The sort descriptors are applied in the order in which they appear in the sortDescriptors array (serially in lowest-array-index-first order).
Code example:
...
NSMutableArray * sortDescriptors = [[NSMutableArray alloc] initWithCapacity:[myArray count]];
for (NSString * key in myArray)
[sortDescriptors addObject:[[NSSortDescriptor alloc] initWithKey:key ascending:NO]];
[fetchRequest setSortDescriptors:sortDescriptors];
[sortDescriptors release];
...
user1800529,
It appears you want the order sequential order things were inserted into your database. Core Data makes no guarantees about that order. Hence, you need to pick something to sort on. I use creation time, which is in most of my entities, but you could easily use another attribute.
Andrew

Fetch Specific Number of Random Rows from CoreData

I'm using the code below to Fetch a queried set of all rows using CoreData matching the search criteria: itemType = 1.
But what I need to do is to Fetch a specific number of Random rows from the data instead.
For example, instead of retrieving all 100 rows of data in which the column name dataType = 1, I need to get 25 rows randomly in which dataType = 1.
I'm hoping there is relatively painless solution.
Any help is appreciated.
lq
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"MyAppName"
inManagedObjectContext:[self managedObjectContext]]];
NSError *error = nil;
NSPredicate *predicate;
NSArray *fetchResults;
predicate = [NSPredicate predicateWithFormat:#"(itemType = %i)", 1];
[request setPredicate:predicate];
fetchResults = [managedObjectContext executeFetchRequest:request error:&error];
if (!fetchResults) {
// NSLog(#"no fetch results error %#", error);
}
self.mutableArrayName = [NSMutableArray arrayWithArray:fetchResults];
[request release];
You can not actually fetch random rows. A reasonable randomization strategy may be to fetch all of the objects matching your predicate, and then randomly select a specific number of objects.
Anyway you can use the following methods of NSFetchRequest:
- (void)setFetchLimit:(NSUInteger)limit
- (void)setFetchOffset:(NSUInteger)limit
Basically, setFetchLimit allows you to define how many rows you want to fetch (in your case you will set limit to 25), while setFetchOffset defines the offset at which rows will begin being returned (see the documentation of the fetchOffset property for details).
This is not a random process, but you may randomly generate the offset. However, it is worth noting here that, depending on the offset, you may then fetch a number of objects falling between zero and your fetch limit.
You could also use reference approach. When you sort by view counts.
I posted long time ago about it: http://www.alterplay.com/ios-dev-tips/2010/06/fetch-random-record-with-coredata.html
Sorry for formatting. it's broken after switching from Blogger to Wordpress.

Core data, sorting one-to-many child objects

So, lets say I have a store of parents children and the parent has a one to many relationship to children (parent.children) and they all have first names. Now, on the initial fetch for parents I can specify a sort descriptor to get them back in order of first name but how can I request the children in order? If I do a [parent.children allObjects] it just gives them back in a jumble and I'd have to sort after the fact, every time.
Thanks,
Sam
If you just want to use an NSArray, and not an NSFetchedResultsController, there's another way:
NSSortDescriptor *alphaSort = [NSSortDescriptor sortDescriptorWithKey:#"firstName" ascending:YES];
NSArray *children = [[parent.children allObjects] sortedArrayUsingDescriptors:[NSArray arrayWithObject:alphaSort]];
Sam,
If I read your question correctly, you want to set up a fetch that returns a sorted list of the children of a specific parent. To do this, I would set up a fetch for "children" entities and then use a predicate to limit the results:
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:#"children" inManagedObjectContext:moc]];
[request setSortDescriptors:[NSArray initWithObject:[[NSSortDescriptor alloc] initWithKey:#"firstName" ascending:YES]];
[request setPredicate:[NSPredicate predicateWithFormat:#"(parent == %#)", parent]];
Obviously, your entity and attribute names may be different. In the last line, the parent variable should be a reference to the NSManagedObject instance of the parent whose children you want.

NSSortDescriptor for NSFetchRequestController causes crash when value of sorted attribute is changed

I have an Core Data Entity with a number of attributes, which include amount(float), categoryTotal(float) and category(string)
The initial ViewController uses a FethchedResultsController to retrieve the entities, and sorts them based on the category and then the categoryTotal. No problems so far.
NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"Transaction" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(dateStamp >= %#) AND (dateStamp =< %#)", startDate, endDate];
[request setPredicate:predicate];
NSSortDescriptor *sortByCategory = [[NSSortDescriptor alloc] initWithKey:#"category" ascending:sortOrder];
NSSortDescriptor *sortByTotals = [[NSSortDescriptor alloc] initWithKey:#"categoryTotal" ascending:sortOrder];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByTotals, sortByCategory, nil];
[request setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:#"category" cacheName:nil];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
On selecting a row (tableView:didSelectRowAtIndexPath), another view controller is loaded that allows editing of the amount field for the selected entity.
Before returning to the first view, categoryTotal is updated by the new ‘amount’. The problem comes when returning to the first view controller, the app bombs with
Serious application error. Exception was caught during Core Data change processing: Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted). with userInfo (null)
Program received signal: “EXC_BAD_ACCESS”.
This seems to be courtesy of NSSortDescriptor *sortByTotals = [[NSSortDescriptor alloc] initWithKey:#"categoryTotal" ascending:sortOrder];
If I remove this everything works as expected, but obviously without the sorting I want.
I'm guessing this is to do with the sorting order changing due to categoryTotal changing (deletion / insertion) but can't find away fix this. I've verified that values are being modified correctly in the second view, so it appears down to the fetchedResultsController being confused. If the categoryAmount is changed to one that does not change the sort order, then no error is generated
I'm not physically changing (ie deleting) the number of items the fetchedResultsController is returning ... the only other issue I can find that seem to generate this error
Any ideas would be most welcome
Thanks, AJ
The ordering of your managed objects via sectionNameKeyPath MUST match the ordering of your managed objects via your primary sort descriptor. Since you are using "category" as your sectionNameKeyPath and yet using "categoryTotal" as your primary sort descriptor, it will not be universally true that the sectionNameKeyPaths have the same ordering as the primary sort descriptor. The reason that removing sortByTotals fixes the problem is that "category" then becomes both the sectionNameKeyPath and the primary sort descriptor, and thus they both have the same ordering.
Try changing your sort in your NSFetchedResultsController to first sort by category and then by categoryTotal. This should resolve the issue. If it does not, please post your NSFetchedResultsController delegate methods.
If categoryTotal is a transient property you cannot sort by this property using a fetch request. You will need to sort the fetchedObjects manually (by code) into a second array which you can use in the table.