how to sort NSMangedObjects by its NSDate attributes - sorting

Question is short:
I have an array of some NSManagedObjects,
all of them have an NSDate attribute
Now I want to sort this arry by their date, the latest the first,
how could implement this?

You want to use NSArray's sortedArrayUsingDescriptors: method with an NSSortDescriptor. If your array is called array and the NSDate attribute is called date, then this would work:
NSArray *sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"date" ascending:NO]];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:sortDescriptors];
Also, note that when you're getting these NSManagedObjects using an NSFetchRequest, you can give the request sortDescriptors so that they're already sorted. Using the same sortDescriptors from above, just do the following before executing the request:
request.sortDescriptors = sortDescriptors;

Related

Filtering with NSPredicate - Data Type?

I wish to filter an array using a predicate but I'm being curved balled with the correct handling of data types.
First off, I have a list I want to filter with:
NSMutableArray *HospitalIDs = [[NSMutableArray alloc]init];
[HospitalIDs addObject: #"1"]; // Must be "id", int & NSInteger not accepted by XCode
[HospitalIDs addObject: #"2"]; // Must be "id", int & NSInteger not accepted by XCode
[HospitalIDs addObject: #"3"]; // Must be "id", int & NSInteger not accepted by XCode
Secondly, I have a list of objects that I want to filter using the array above:
(It's defined as NSMutableArray *HospitalObjects and is pre-populated with HospitalObjects)
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.HospitalID IN %#", HospitalIDs];
[HospitalObjects filterUsingPredicate:predicate];
NSLog(#"%i",[HospitalObjects count]);
//The expected result is 3, but it prints 0.
WHY?
Because by first array contains NSString values, but my HospitalObject.HospitalID is of type int.
I don't really want to change the data type of HospitalID in my object definition to NSString, but I cannot filter on integer values, what do I do?
Can I convert the data type WITHIN the predicate syntax? How?
First of all, the best way to store numbers in NSArray is to use NSNumber objects. You can simply convert a NSInteger to NSNumber using Objective-C literal syntax:
[HospitalIDs addObject: #(1)];
[HospitalIDs addObject: #(2)];
[HospitalIDs addObject: #(3)];
Then your predicate should work without any further changes.
There is a Type NSNumber that wraps ints, floats, bools, .. in a object.
NSMutableArray * hospitalIDs = [[NSMutableArray alloc] init];
[hospitalIDs addObject: #1]; // You can wrap an normal int into an NSNumber jusing #. In some siztuations you have to use #(yourOrdinaryValueTypeVariable)
[hospitalIDs addObject: #2];
[hospitalIDs addObject: #3];
By the way try to use proper naming using CamelCase:
Classes start with a upper case: SomeClassName
Objects, variables and method names with lower case: `SomeClassName* someObject;
Constants are all upper case: MY_CONSTANT

Building up an array an element at a time

Currently I'm populating an array in one line, e.g.
self.monthMonths = [[NSArray alloc] initWithObjects:#"January", #"February", #"March", #"April", #"May", #"June",#"July",#"August",#"September",#"October",#"November",#"December", nil];
What is the syntax to add these elements one at a time as I want to pull the data from a database. I'm using the months of the year as an example.
while([results next]) {
NSString *months = [results stringForColumn:#"month"];
self.month = [[NSArray alloc] initWithObjects:#"month",nil];
//[NSArray
NSLog(#"Month: %#",month);
}
Create an NSMutableArray and add the objects to it one by one with addObject
You need to use NSMutableArray instead, and call -addObject:

avoid duplicate results on Core Data fetch

I have a subclass of the CoreDataTableViewController (subclass of UITAbleViewController dome by the people on Stanford done to link CoreData and TableViews). On this Class, I want to perform a fecth, sorting by an attribute called "definition" and the code which executes it is the following:
- (void)setupFetchedResultsController{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:self.entity];
request.propertiesToFetch=[NSArray arrayWithObject:#"definition"];
request.returnsDistinctResults=YES;
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"%K != nil", #"definition"];
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"%K != ''", #"definition"];
NSPredicate *predicate3= [NSPredicate predicateWithFormat:#"%K contains[cd] %#", #"definition", self.seachBar.text];
NSArray *prepredicateArray;
if ([self.seachBar.text length]) {
prepredicateArray = [NSArray arrayWithObjects:predicate1, predicate2, predicate3,nil];
}else {
prepredicateArray = [NSArray arrayWithObjects:predicate1, predicate2,nil];
}
request.predicate=[NSCompoundPredicate andPredicateWithSubpredicates:prepredicateArray];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"definition" ascending:YES ]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
[self performFetch];
}
If I understood it correctly, setting request.returnsDistinctResults=YES; should avoid fetching duplicates. However it doesn't work and I'm seeing duplicates of this attribute's value.
Is there something I'm missing there? I'd appreciate some pointings there. Thank you in advance.
EDIT: If anyone is having the same issue here, after applying David's answer the resulting fetchedResultsController is just a NSDIctionary with object with only the requested value, which for displaying only purposes is quite fine. One thing I've done in cellForRowAtIndexPath in order to display the results on the cell label is:
Before:
HNMR *hnmr = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text=hnmr.definition;
After:
cell.textLabel.text=[[self.fetchedResultsController objectAtIndexPath:indexPath] valueForKey:#"definition"];
From the documentation of returnsDistinctResults:
This value is only used if a value has been set for propertiesToFetch.
From the documentation of propertiesToFetch:
This value is only used if resultType is set to NSDictionaryResultType.
From the documentation of resultType:
The default value is NSManagedObjectResultType.
This all tells me that the propertiesToFetch is ignored because you haven't set the resultType yourself and the default it to return managed objects instead of dictionaries. Since the propertiesToFetch is ignored the returnsDistinctResults is ignored as well and thus you are still getting duplicates.
Try setting the result type to return dictionaries instead of managed objects.
request.resultType = NSDictionaryResultType;
In addition to David Rönnqvist answer I suggest a useful link (with a sample) on selecting distinct values with Core Data:
core-data-how-to-do-a-select-distinct
Hope that helps.

Sort a NSMutableArray in objective-c?

I am working on NSMutable Array containing list of "First Name" in it.I want to sort it alphabatically.
I tried this code
NSSortDescriptor * sortFriend = [[[NSSortDescriptor alloc] initWithKey:kfirstName ascending:YES] autorelease];
NSArray * descriptors = [NSArray arrayWithObject:sortFriend];
NSArray * sorted = [Friendsarr sortedArrayUsingDescriptors:descriptors];
correct me if i am wrong.I do have an array of names also if that could be used.
Thanks
I tried the code
NSSortDescriptor * sortFriend = [[[NSSortDescriptor alloc] initWithKey:kfirstName ascending:YES selector: #selector(caseInsensitiveCompare:)] autorelease];
NSArray * descriptors = [NSArray arrayWithObject:sortFriend];
NSArray * arrmp = [temparray sortedArrayUsingDescriptors:descriptors];
But still my result contain 2 'k' chars. one 'k' and 'K'.I want to have case insensitive result
If your NSMutableArray only contains objects of type NSString, simply do:
[myMutableArray sortUsingSelector:#selector(compare:)];
You can sort NSMutable array case insensitively by this code
NSSortDescriptor *sorter=[[[NSSortDescriptor alloc] initWithKey:nil ascending:YES selector:#selector(caseInsensitiveCompare:)]autorelease];
NSArray *sortdescriptor=[NSArray arrayWithObject:sorter];
[cpy_arr_Service_Name sortUsingDescriptors:sortdescriptor];
I found the solution of sorting NSMutableArrays with sample code which can be found on the site below.
http://www.icodeblog.com/2010/12/10/implementing-uitableview-sections-from-an-nsarray-of-nsdictionary-objects/
I hope it help others to as it provides indexed sorting of a grouped table view using an array as the datasource

How to sort NSMutableArray of NSMutableDictionary?

I have NSMutableArray of NSMutableDictionary(NSString objects). One of NSString object is actually a date, and i need to sort NSMutableArray based on that date and I don't want it to sort dates as strings. How can i make it?
If I understand correctly, your array contains dictionaries that contain strings and you want to sort on those strings... as dates. Something like this perhaps:
[someArray sortWithOptions: 0 usingComparator: ^(id inObj1, id inObj2) {
NSDate *date1 = [NSDate dateWithString: [inObj1 objectForKey: #"dateString"]];
NSDate *date2 = [NSDate dateWithString: [inObj2 objectForKey: #"dateString"]];
return [date1 compare: date2];
}];
You will need to use the sortedArrayUsingFunction:context: method. For example:
NSInteger comparator( NSDictionary *d1, NSDictionary *d2, void *context )
{
return [[d1 objectForKey:#"date"] compare:[d2 objectForKey:#"date"]];
}
// In some method:
NSArray *sortedArray = [array sortedArrayUsingFunction:comparator context:nil];
Note: This is not tested.

Resources