How do I filter my array to display only specific category items? - nsmutablearray

This code currently lists all my categories. However I will like to filter this result to display specific results. For example... The array contains the items Jamaica, Japan, Germany and Asia. I will like to filter the displayed results to only show Japan and Germany. I've read NSPredicate can assist me but i'm not too sure on how to implement it here.
Datacontroller.M
+(NSArray*) getCategories {
AppDelegate* delegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
NSManagedObjectContext* context = delegate.managedObjectContext;
NSError *error;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"StoreCategory" inManagedObjectContext:context];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"created_at" ascending:YES];
[fetchRequest setSortDescriptors:#[sortDescriptor]];
[fetchRequest setEntity:entity];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
return fetchedObjects;
}
Categories.m
-(UITableViewCell*)MGListView:(MGListView *)listView1 didCreateCell:(MGListCell *)cell indexPath:(NSIndexPath *)indexPath {
if(cell != nil) {
StoreCategory* cat = [listViewMain.arrayData objectAtIndex:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];
[cell.labelTitle setText:cat.category];
[self setImage:cat.category_icon imageView:cell.imgViewThumb];
}
return cell;
}

You cannot filter the unwanted category in this method because indexPath will be a sequence of indices.
You will have to build another array that includes the category you want before UITableView delegate or DataSource functions are called, for example, in ViewDidLoad.

This method seemed to do the trick.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"category CONTAINS[cd] %# OR category CONTAINS[cd] %#", #"Japan", #"Germany", context];
[fetchRequest setPredicate:predicate];

Related

coredata subquery with multiple conditions / relations

I have the following model:
how can I get all the PT objects where groupId == '2'?
I have tried several ways, but without success.
With this query, I get one result only:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"Status" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"group.groupId == %#", [NSNumber numberWithInt:2]];
NSError *error = nil;
NSArray *resultSet = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSLog(#"array count: %lu", (unsigned long)[resultSet count]);
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"hasBeenDeleted == %# AND (ANY hasStatus IN %#)",
[NSNumber numberWithBool:NO],
[NSSet setWithArray:resultSet]];
[self.ptListViewController refreshDataWithPredicate:thePredicate];
You could start with a template "GROUP_BY_GROUP_ID" and add it to the managedObjectModel ...
- (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"GroupdId2" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSFetchRequest *tmpTemplate;
NSEntityDescription *tmpEntity;
NSPredicate *tmpPredicate;
// 1. GROUP_BY_GROUP_ID
tmpEntity = [[_managedObjectModel entitiesByName] objectForKey:#"Group"];
tmpTemplate = [[NSFetchRequest alloc] init];
[tmpTemplate setEntity:tmpEntity];
tmpPredicate = [NSPredicate predicateWithFormat:#"(groupId == $value)"];
[tmpTemplate setPredicate:tmpPredicate];
[_managedObjectModel setFetchRequestTemplate:tmpTemplate forName:#"GROUP_BY_GROUP_ID"];
return _managedObjectModel;
}
Here is the appropriate fetch method:
- (NSArray *)fetchGroupByGroupId:(NSNumber *)value
{
NSError *error = nil;
NSManagedObjectModel *model = _managedObjectModel;
NSDictionary *substitutionDictionary = [NSDictionary dictionaryWithObjectsAndKeys:value, #"value", nil];
NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:#"GROUP_BY_GROUP_ID" substitutionVariables:substitutionDictionary];
NSArray *results = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
return results;
}
Now you can start fetching PT entities like this (Xcode lets you generate the NSManagedObject subclasses for all entities):
NSArray *groups=[self fetchGroupByGroupId:#(2)];
NSMutableSet *resultPT=[[NSMutableSet alloc] init];
for (Group *group in groups) {
for (Status *status in group.hasStatus) {
for (PTStatus *ptstatus in status.ptStatus) {
if (ptstatus.targetPT!=nil) {
[resultPT addObject:ptstatus.targetPT];
}
if (ptstatus.pt!=nil) {
[resultPT addObject:ptstatus.pt];
}
}
}
}
In resultPT now you will find all different PT entities "with" groupId == '2'.
You find a XCode 6.1 project here: XCode 6.1 project on Dropbox.
Hope it helps.
I found it!
I had a bug when relating the Status with the Group.
Correct code for achieving:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"PTStatus" inManagedObjectContext:self.managedObjectContext];
request.predicate = [NSPredicate predicateWithFormat:#"ANY status.group.groupId == %#", [NSNumber numberWithInt:2]];
NSError *error = nil;
NSArray *resultSet = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
NSLog(#"array count: %lu", (unsigned long)[resultSet count]);
NSPredicate *thePredicate = [NSPredicate predicateWithFormat:#"hasBeenDeleted == %# AND (ANY hasStatus IN %#)",
[NSNumber numberWithBool:NO],
[NSSet setWithArray:resultSet]];
[self.ptListViewController refreshDataWithPredicate:thePredicate];
and [self.ptListViewController refreshDataWithPredicate:thePredicate]; has
- (void)refreshDataWithPredicate:(NSPredicate *)predicate{
self.fetchedResultsController = nil;
[NSFetchedResultsController deleteCacheWithName:#"PTs_Cache"];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = [NSEntityDescription entityForName:#"PT" inManagedObjectContext:self.managedObjectContext];
request.sortDescriptors = [NSArray arrayWithObjects:
[NSSortDescriptor sortDescriptorWithKey:#"requestDate" ascending:NO],
[NSSortDescriptor sortDescriptorWithKey:#"number" ascending:YES],
nil];
request.predicate = predicate;
request.fetchBatchSize = 40;
NSString *sectionNameKeyPathString = #"dateSection_transient";
NSFetchedResultsController *frc = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:sectionNameKeyPathString
cacheName:#"PTs_Cache"];
[request release];
self.fetchedResultsController = frc;
[frc release];
[self.theTable reloadData];
}

Core Data input fetches into labels

I want to store data from a text field. And then use this data to populate the text in a label inside a view controller. Is this possible? Ive messed around with it, but nothing seems to work. Any thoughts? Here are my two methods...
- (IBAction)saveButton:(id)sender {
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSManagedObject *noteEntry = [NSEntityDescription insertNewObjectForEntityForName:#"Notes" inManagedObjectContext:coreDataStack.managedObjectContext];
[noteEntry setValue:_notesField.text forKey:#"notes"];
NSError *error = nil;
// Save the object to persistent store
if (![coreDataStack.managedObjectContext save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
[coreDataStack saveContext];
}
Here is my view did load method:
- (void)viewDidLoad
{
[super viewDidLoad];
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Notes"];
Notes *entry = [NSEntityDescription insertNewObjectForEntityForName:#"Notes" inManagedObjectContext:coreDataStack.managedObjectContext];
_outputLabel.text = entry.notes;
}
Your code in the saveButton: method seems OK. But your code in the viewDidLoad method seems wrong. Are you trying to do the following?
- (void)viewDidLoad {
[super viewDidLoad];
CoreDataStack *coreDataStack = [CoreDataStack defaultStack];
//First way to init your fetchRequest:
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:#"Notes"];
//Second way to init your fetchRequest:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Notes" inManagedObjectContext:coreDataStack];
[fetchRequest setEntity:entity];
//Having a NSEntityDescription object can be usefull if you need to group your data, for example
//Set some predicates, if necessary
//Set some sortdescriptors, if necessary
NSError *error;
NSArray *resultsArray = [coreDataStack executeFetchRequest:request error:&error];
NSLog(#"%#", resultsArray);
_outputLabel.text = [[resultsArray firstObject] notes]; //if your array can only have one object
}
The NSLog will give you the structure of your fetch array (I can't guess it). You will then be able to set _outputLabel.text.
Answer by #user1966109 is exactly correct answer what you are looking for. Since you need to show the text in a label and for that you need to set predicate to get a single row. Set the predicate as below
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"value == abc"];//considerin abc is the word you are looking for.
request.predicate = predicate;
//then execute the query.

NSPredicate with 20 last records

I'm working with core data and I try to get last 20 records using setFecthLimit but in these last records I want to get count of unreads, I use this
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Post" inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
[request setFetchLimit:20];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isRead = NO OR isRead = NIL"];
[request setPredicate:predicate];
NSError *error = nil;
NSMutableArray *records = [[_managedObjectContext
executeFetchRequest:request
error:&error] mutableCopy];
but it always return me 20, can anyone help me please?
A simple solution is to remove the predicate. Grab 20 objects and then filter them based on the predicate.
For example:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Post" inManagedObjectContext:_managedObjectContext];
[request setEntity:entity];
[request setFetchLimit:20];
NSError *error = nil;
NSArray *records = [_managedObjectContext executeFetchRequest:request
error:&error];
// do some error checking here...
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isRead = NO OR isRead = nil"];
// [NSPredicate predicateWithFormat:#"isRead = %#", [NSNumber numberWithBool:NO]];
NSArray *filteredRecords = [records filteredArrayUsingPredicate:predicate];
I think you have a typo in your predicate format:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Post"]
request.fetchLimit = 20;
request.predicate = [NSPredicate predicateWithFormat:#"(isRead == NO) OR (isRead == NULL)"];
NSSortDescriptor = [...insert your sort descriptor code here...]
request.sortDEscriptos = #[sd];
And remember to sort, such that you get the last 20, not just a random 20.

Coredata for getting all the values of a field

I have an entity ("Settings") and I want to get all the values in just one field ("Status").I am using coredata. Can anyone help me, please?
Declare this in .h file:
NSMutableArray *eventArray;
and in .m file
- (void)fetchRecords {
// Setup the fetch request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Define our table/entity to use
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Settings" inManagedObjectContext:managedObjectContext];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Status" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
[fetchRequest setEntity:entity];
[fetchRequest setEntity:entity];
NSError *error;
// Get array of results.
NSMutableArray *theResults = [[managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
if (!theResults) {
// Handle the error.
// This is a serious error and should advise the user to restart the application
}
// Grab unique neighborhoods through NSSet.
NSSet *uniqueElements = [NSSet setWithArray:[theResults valueForKey:#"Status"]];
// Dump NSSet uniques into new array.
NSMutableArray *sortedResults = [[NSMutableArray alloc] initWithArray:[uniqueElements allObjects]];
for(int i = 0; i < [sortedResults count];i++)
{
NSLog(#"%d. %#", i+1, [sortedResults objectAtIndex:i]);
}
// Save our fetched data to an array
[self setEventArray: sortedResults];
}
At first, u can get Array of values:
NSFetchRequest *requestSettings = [[NSFetchRequest alloc] init];
[requestCodesList setEntity:[NSEntityDescription entityForName:#"Setting" inManagedObjectContext:managedObjectContext]];
NSArray *setting = [managedObjectContext executeFetchRequest:requestCodesList error:&error];
if (error) NSLog(#"Failed to executeFetchRequest to data store: %#", [error localizedDescription]);
Next, u transfer u array in NSString:
ComponentsJoinedByString: Constructs
and returns an NSString object that is
the result of interposing a given
separator between the elements of the
array.
(NSString *)componentsJoinedByString:(NSString *)separator
code is:
NSString *settingChanged = [setting componentsJoinedByString:#","];
And after u can using this anywhere in u UI (binding, setStringValue e.t.c)

NSPredicate for an NSManagedObject's string attribute's length

Could someone please help me define a predicate that returns only NSManagedObject's who's "letters" attribute length is within a certain range?
Here's the example I've been trying, I've got a feeling it's the letters.length notation, I've also tried the kvc letters.#length with no success.. What am I doing wrong?
NSManagedObjectContext *context = ...;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Word" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"letters" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"letters.length BETWEEN %#", [NSArray arrayWithObjects: [NSNumber numberWithInt:5], [NSNumber numberWithInt:20], nil]];
[fetchRequest setPredicate:predicate];
NSUInteger limit = 20;
[fetchRequest setFetchLimit:limit];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
Not sure how this code snippet is performance wise but here is my answer to your question:
NSString *attributeName = #"letters";
NSString *attributeValue = [NSString stringWithFormat:#"'.{%d,%d}'", 5, 20];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K MATCHES %#", attributeName, attributeValue];
[fetchRequest setPredicate:predicate];
Joss.
I've got some bad news. You can't do this. There is no length attribute for strings in the NSPredicate (that I've been able to find).
What I would recommend you do is add an attribute for the length of the stored string in your managed object that gets set when you set the letters attribute. You can then do your query on that attribute and return the values you want.
In case someone is looking for a way to test whether a string has length using an NSPredicate,
it is possible.
Swift:
returns strings with 4 to 7 characters.
NSPredicate(format: "text MATCHES %#", ".{4,7}")

Resources