Fetching entities with different number of parameters - ios

I have several entities with more or less the same parameters but in different numbers.
For example:
EntityA : model, code, color, name
EntityB : model, code, color, name, country
EntityC : model, code, color, name, country, style, date
Because of this, I did not create classes for the entity, so it is convenient to add stuff to "entityA" by doing this:
NSArray *keys = #[#"model", #"code", #"color", #"name"];
NSManagedObject *newObjectOnEntity = [NSManagedObject newObjectOnEntity:#"entityA"
inManagedObjectContext:self.managedObjectContext];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
[newObjectOnEntity setValuesForKeysWithDictionary:dict];
I simply add more entries to keys and values and I can use the same code to add stuff to all entities.
But now comes the fetch part.
At this point I need to do a fetch like this on lets say entityA:
fetch entry for (model = "abc") && (code = "zoltrix") && (color = "blue") && (name = "roger")
if the entity is B, the fetch will also have && (country = "usa") and if entity is C will also have style and date.
So what I am asking is if I can have a fetch where I pass an array of parameters, an array of values and it searches for the entry on that entity that matches all parameters and values (parameter1 == value1) && (parameter2 == value2) ...

So what I am asking is if I can have a fetch where I pass an array of parameters, an array of values and it searches for the entry on that entity that matches all parameters and values
Sure you can. In the NSPredicate syntax you can specify the field name with %K and the value with %# (or other format specifiers).
(Check out "Dynamic Property Names" in the "Predicate Programming Guide".)

Related

IOS/Objective-C: Search string element with array of objects

As part of an autocomplete box, I am searching names within an array of contacts. However, after the user picks a name from the suggested List, I need to grab the id of the contact which is in the array of contact objects but not the array of names that appear in the suggest box. I've been working with just the names as that's what I want to display in the suggestion box but have an array of contacts as well.
How would I convert code below (probably using key values) to search the name dimensions of an array of objects instead of an array of names so as to keep track of the ids of the objects. I am kind of fuzzy on arrays and key values.
//the array being searched looks something like #[#"John", #"Dave", #"Sam", #"Xian", #"Ahmed", #"Johann"];
//I want to search the names in an array that looks something like:
(
{
first = "John";cid = 2;},
{
first = "Dave";cid = 44;},
{
first = "Xian";cid=99})
//this code works great to search names but I lose track ids. Thank you for any suggestions.
-(void)searchArray: (NSMutableArray*) array forString: (NSString *) term {
[_contactsSuggested removeAllObjects];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",term];
NSArray *tempArray = [array filteredArrayUsingPredicate:predicate];
_contactsSuggested = [NSMutableArray arrayWithArray:tempArray];
[_autocompleteTableView reloadData];
}
Create a Contact object. Give it a name property, an id property, and any other properties you need. Then write code that searches an array of Contact objects rather than just an array of names. You could then create a predicate using predicateWithBlock to filter the items that match your name property.

Fetch Realm objects that contain parameter

I have a realm database filled with Restaurant objects that have a url parameter. I'd like to fetch the objects where the url contains what the user has typed in a UITextField.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"url CONTAINS '%#'", self.searchQuery];
RLMResults<Database *> *results = [Database objectsWithPredicate:pred];
if ([results count] == 0) {
NSLog(#"results count == 0");
return nil;
}
Now, when I run this, I always get 0 results. Eventhough I have two example entries that have 'http://www.testingthis.com' as an url and the search query is 'testingthis'. Any ideas as to why I'm not getting results?
You need to perform your search query against the Restaurant class itself; not Database. Realm uses the class you specify to determine which table in which to apply the query.
As an aside, you can also inline NSPredicate queries with +[RLMObject objectsWhere:], so it's not necessary to create a separate NSPredicate object (unless you've got a specific reason). :)
RLMResults *restaurants = [Restaurant objectsWhere:#"url CONTAINS '%#'", #"testingthis"];
If you're trying to query for Restaurant objects that aren't in the default Realm, then you can alternatively use +[RLMObject objectsInRealm: where:] to explicitly control which database you're querying.

NSFetchedResultController complex sort case

I have following data model:
[Agency] <--->> [AgencyRating] <<---> [RatingType]
There are numbers of rating types (ex. overall, branding, design, programming, etc). Each agency can have all these rating types (ex. agency FooBar has 1050 points in design and 700 points in branding).
Tables structures:
Agency: name:string
RatingType: name:string
AgencyRating: agency_ref: relationship to agency, ratingType_ref: relationship to rating type, value: Integer.
I have split view controller. Left side contains available rating types. When user picks any rating type, I'd like to show sorted by rating value agencies on the right side.
I'd like to achieve it with NSFetchedResultController. I understand how to get rating values to display it in cells, but I don't understand how to make a sort descriptor.
Currently I have:
Controller:
_contentFetchController = [Agency MR_fetchAllGroupedBy:nil withPredicate:[NSPredicate predicateWithValue:YES] sortedBy:#"name" ascending:YES];
Cell:
- (void) configureForAgency:(Agency *) agency ratingType:(RatingType *) ratingType forIndexPath:(NSIndexPath *) path {
self.positionLabel.text = [NSString stringWithFormat: #"%d", (int)path.row + 1];
UIImage *image = [UIImage imageWithContentsOfFile:agency.logoPath];
if (image) {
self.logoImageView.image = image;
}
self.nameLabel.text = agency.name;
// HERE IS VALUE OF RATING
self.ratingValueLabel.text = [[agency ratingForRatingType:ratingType] stringValue];
}
As you can see: I sort by name, but I need to sort by rating value, based on selected rating type. Any ideas?
In order to do that you need to fetch Agencies, that have an associated AgencyRating with a selected rating type and sort everything by rating value.
I assume that rating type is ratingType, rating value is ratingValue and AgencyRating association is agencyRatings. I also assume that each agency can have only one agency rating of each rating type (if not, you will have to sort by the SUM of all agency ratings of selected type).
Judging by the MR_ prefix, I guess you are using MagicalRecord, which I'm not familiar with, but here's how you can do that with plain NSFetchRequest and NSFetchedResultsController.
First you will need to set up a NSFetchRequest:
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Agency"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"ANY agencyRatings.ratingType = %#", ratingType];
fetchRequest.sortDescriptors = #[ [NSSortDescriptor sortDescriptorWithKey:#"agencyRatings.ratingValue" ascending:YES] ];
Then you can set up the NSFetchedResultsController as you would normally do providing it with the fetchRequest you just created.
Every time the user changes the ratingType you will need to change the fetchRequest's predicate and call performFetch on the fetchedResultsController.
I guess you need to adjust this a little bit to fit your case, but the idea is to to have a predicate and a sort descriptor that are pointing to a related table.

Nested core data fetch

I have a core data DB with multiple entities. There is a parent entity called "Person" which has many "Friends", "Friends" have many "Activities", and "Activities" have "Types" ("Types has a to-many relationship to "Activities"). What I'm trying to achieve is filtering all the "Person" entities by "Types". A user would be tapping on a "Type" and then I would refresh my table and filter the "Person" entities that are displayed by the "Types" that are associated with them.
Currently I'm thinking I have to use a compound predicate but I'm completely sure how to go about it. So far all I've done is printed out the values I've wanted by looping through my fetchedObjects like so:
NSArray *persons = self.fetchedResultsController.fetchedObjects;
for (JIPerson *person in persons) {
JIFriend *friend = person.friends.anyObject;
JIActivity *activity = friend.activities.anyObject;
JIType *type = activity.type;
NSLog(#"%#", type.name);
}
This prints out the values correctly, but I need to filter my table using these values. How can I achieve that?
Seems like I got it. Using NSPredicate you can traverse a deep relationship like this using dot notation. My implementation went as follows:
- (void)filterPersonByType:(NSString *)typeName {
NSPredicate *typePredicate = [NSPredicate predicateWithFormat:#"ANY friends.activities.type.name CONTAINS[cd]%#", typeName];
}
Yes, you can use dot notation with NSPredicate. You might want to have the type be an actual type, though, that would be cleaner than just doing string comparisons.

NSPredicate filter array but return only one field of an object

I'm sure this question has been asked but I don't know what to search on.
I have array of Message objects with the following fields {selected[BOOL], messageText[STR]}. I want to filter this array to get only the objects with selected=TRUE. So far so good.
NSArray *messagesFiltered = [self.fetchedResultsController.fetchedObjects filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"selected == TRUE"]];
However, I don't need the objects themselves in the returned array, I need an array of the messageText strings. How to modify predicate to return only the messageText strings and not the whole object?
That's not really the job of a predicate. Predicates are only for filtering, not modifying, the array you apply them to.
However, there's a fun little trick: the method -valueForKey: will apply the kind of transform you want to your array. Just call it with the messageText key that you want:
NSArray *messagesFiltered = [self.fetchedResultsController.fetchedObjects filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"selected == TRUE"]];
NSArray *realMessages = [messagesFiltered valueForKey:#"messageText"];
On an array, -valueForKey: asks each element for a value for the given key, then returns an array of everything the elements returned. (Any element that returns nil for the key you pass shows up as [NSNull null] in the resulting array.)

Resources