In a previous question, a user asked for a method to order core data objects inside a UITableView Section. I am in the same case, but I don't find the way to implement the proposed solution.
The proposed solution was to create the following method:
- (NSArray*)sortedSectionForIndex:(NSInteger)index
{
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"priority" ascending:YES];
id section = [[self fetchedResultsController] sections][index];
NSLog(#"INDEX********* = %ld", (long)index);
NSArray *objects = [section objects];
NSArray *sorted = [objects sortedArrayUsingDescriptors:#[sort]];
return sorted;
}
But I don't know how to call this method inside my code in the way that the section objects would be ordered.
Thank you.
You should implement separate fetchedResultsController(s) and sort descriptor for the section(s) you want sorted differently. Take a look at the CompanyMenuTableViewController code in this sample app. One of the sections uses it's own fetchedResultsController. You would use a similar approach to handle each section independently of other sections, with each section having its own fetchedResultsController if necessary.
Make sure you download the most recent version.
http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/
Related
When sorting an array of character strings, I learned that sorting can be done easily with the following code.
arr = [arr sortedArrayUsingSelector: #selector (localizedStandardCompare :)];
However, this time I want to rearrange the instance of the custom class.
* String information can be obtained from the instance method of the custom class.
So by returning NSComparisonResult using the following block sort
I thought that I could rearrange the instance of the custom class, but
It did not move as I expected.
- (NSArray <ObjectType> *) sortedArrayUsingComparator: (NSComparator) cmptr;
If you understand, please let me know.
Thank you.
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"Your Key" ascending:NO];
NSArray *sortedArray=[yourArrayName sortedArrayUsingDescriptors:#[sort]];
I'm trying to sort a property on a type of a mutable array.
However I've only managed to sort a NSString array.
NSMutableArray<DBFILESFileMetadata*> *tmpArray = [[NSMutableArray alloc]init];
for (DBFILESMetadata *entry in entries)
{
//conditions
[tmpArray addObject:fileMetadata];
}
Here's the type / class
https://github.com/dropbox/dropbox-sdk-obj-c/blob/4c99bdf726cf9724adfddc19e71a87a6012eddeb/Source/ObjectiveDropboxOfficial/Shared/Generated/ApiObjects/Files/Headers/DBFILESMetadata.h
I've tried
[yourArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
and
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
[yourArray sortUsingDescriptors:[NSArray arrayWithObject:sort]];
The property is called name.
I've seen answer like this How can I sort an NSMutableArray alphabetically? but I can't seem to get this to work for my scenario.
In order to sort using sortUsingSelector you need to implement your compare method in the objects that you are trying to compare. (So your DBFILESMetadata class would need a compare method - localizedCaseInsensitiveCompare in the code above.)
You should be able too use a sort descriptor as you show in your second attempt. What happens when you do that?
A third way to do it is to use the NSMutableArray sortUsingComparator and write an NSComparator block that compares the 2 objects.
I'm out of practice with Objective-C but a quick Google search found an example, which I adapted to your specific problem:
[entries sortUsingComparator:
^NSComparisonResult(DBFILESMetadata *obj1, DBFILESMetadata *obj2)
{
return [obj1.name localizedCaseInsensitiveCompare: obj2.name];
}];
That should work, although as I say I'm out of practice in Objective-C, and its block syntax is pretty awkward and counter-intutive.
Thanks to a more expert user, I have implemented a method to sort core data objects inside a table view section. The sorting method inside the section is different to the sorting method of the table view. The latest is done by a NSFetchedResultsController. But now I don't know how to get the values from the sorted NSArray.
This is the method that sorts the core data objects inside a section:
- (NSArray*)sortedSectionForIndex:(NSInteger)index
{
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:#"priority" ascending:YES];
id section = [[self fetchedResultsController] sections][index];
NSLog(#"INDEX********* = %ld", (long)index);
NSArray *objects = [section objects];
NSArray *sorted = [objects sortedArrayUsingDescriptors:#[sort]];
return sorted;
}
And this is the code added to the cellForRowAtIndexPat method to get the NSArray from the sortedSectionForIndex method:
NSArray *sorted = [self sortedSectionForIndex:[indexPath section]];
id object = [sorted objectAtIndex:[indexPath row]];
NSLog(#"OBJECTV= %#",object);
Now, I would need to know how to show the values from the array to be put as cell.textlabel:
A second question is that I don't know if getting the core data object from the array will change the way to handle them for the rest of the methods. I mean, before implementing this sorting method, when the user clicks on a row, a detail view from the selected object was shown. Now getting the objects from an array and not from the NSFetchedResultsController, I am not sure if it will continue working as before.
I would change the line
id object = . . .
To
NSManagedObject *object = . . .
And then
cell.textLabel = [object valueForKey:#"todoName"];
I have a POS type app that uses Core Data to store daily sales transactions using table views. I am attempting to retrieve and update certain Core Date Properties, like daily sales counts, WITHOUT using table views. Table views use row at index path to point to the correct object (row). I am using the Fetched Results controller with a predicate to retrieve the fetched object (row) Question: How do I obtain the index of the fetched row so that I can retrieve and then update the correct property values? All books and examples use table views to change properties.
Entity Product
Product *product;
______________________________
[self setupFetchedResultsController]; (This returns one object)
product = [NSFetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; (objectAtIndexPath - Errors of course)
I think you shouldn't use NSFetchedResultsController in this case. If you don't want to use it in either a UITableView or a UICollectionView, you're probably better of without it. You're probably better of using a NSFetchRequest instead, it's pretty easy to set up:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Entity"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"someValue=1"];
fetchRequest.predicate = predicate;
NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
Now you have a NSArray with all the results, which you could use without having to deal with index paths.
If you're still using a NSFetchedResultController for a table (I'm not sure if you do), those rows will still be updated whenever you make a change.
Update: To update one of the objects returned by the fetch, could be done like this:
Entity *entity = [array firstObject];
[entity setSomeProperty:#"CoreDataIsAwesome"];
NSError *error = nil;
if ([self.managedObjectContext save:&error]) {
NSLog(#"Entity updated!");
} else {
NSLog(#"Something went wrong: %#", error);
}
You can use the method indexPathOfObject: on your fetched results controller to return the index path of the given object to then do your updates.
I have a UITableView that adds information from a Core Data the following way:
The "Category" for various names is added at the header
The names that correspond to the Category should be loaded in cells beneath the Category
Right now I have the header loading the right name and the right number of sections and rows being added. However - the results from Core Data are being returned as an NSSet, so I can't add each name to the cells based on the indexPath.row.
Any suggestions? For reference:
cell.textLabel.text = [NSString stringWithFormat:#"%#",[[[dataToUse objectAtIndex:indexPath.section]valueForKey:#"heldBy"]valueForKey:#"name"]];
Returns the appropriate set of names to each cell of the appropriate section, but it returns the ENTIRE set to each cell. I just want each name to be added based on which row it's a part of. I can solve this by converting the NSSet to an Array, but since there are multiple sets being created (because there are multiple categories) I don't see how I can do this.
EDIT: I fixed my problem by doing the following, but I'm still interested to know what the best thing to do would have been.
NSSet *daset = [[dataToUse objectAtIndex:indexPath.section]valueForKey:#"heldBy"];
NSMutableArray *addToLabel = [[NSMutableArray alloc]init];
int i = 0;
for(NSSet *contact in daset) {
[addToLabel insertObject:[contact valueForKey:#"name"] atIndex:i];
NSLog(#"%#",addToLabel);
i++;
}
cell.textLabel.text = [NSString stringWithFormat:#"%#",[addToLabel objectAtIndex:indexPath.row]];
Use an NSFetchedResultsController
It's designed to do exactly what you're looking for. For straight forward cases like yours, where you just need your data organized into sections based on your model relationships it will offload a lot of weight off your shoulders by automatically managing the fetching, editing, caching etc. You can find a nice tutorial here and of course the official documentation here.
To convert from NSSet->NSArray you need to sort the set with a NSSortDescriptior. Something like:
NSSortDescriptor *sort=[[NSSortDescriptor alloc] initWithKey:#"nm" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *arr = [[myset allObjects] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSSortDescriptor *sort=[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *arr = [[myset allObjects] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
"nsset object" *nssetObject =[arr objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#",nssetObject.name];