iOS coredata predicate: How to predicate the primitive value? - ios

I have a bit a nasty problem. In coredata I have an entity called "Category" and I want to have a default category, a user cannot delete, edit etc. This default category is called "0_default_category" (stored in the constant kSettingsLocalizedDefaultCategory) and this name gets replaced by a localized string when displayed to the user. For that I have overwritten the getter:
-(NSString *)name
{
if([[self primitiveValueForKey:#"name"] isEqualToString:kSettingsLocalizedDefaultCategory]){
return NSLocalizedString(kSettingsLocalizedDefaultCategory, nil);
} else {
return [self primitiveValueForKey:#"name"];
}
}
Now of course I want to use the predicate on the constant and not the localized string! But this uses the predicate on the localized string (so my getter is called, which I don't want..)
request.predicate = [NSPredicate predicateWithFormat:#"name != %#", kSettingsLocalizedDefaultCategory];
Any idea how I can predicate the primitive value?

I think you are conflating two separate issues. One is the fact that you have some special logic (your constant) to automatically display a localized string. The other is to return the value stored in the attribute name.
Ideally, these should be separated to make these two issues explicit. Thus, you should not override the getter of name but instead just create a custom method (or a derived attribute, according to your needs) with a different name.
-(NSString*)displayName {
return [self.name isEqualToString:kConstant] ?
NSLocalizedString(kConstant) : self.name;
}
Use displayName if you want to display your name using your custom logic, and keep the predicate as
[NSPredicate predicateWithFormat:#"name != %#", kConstant];

Related

realm objectsWhere doesn't work

I'm trying to fetch realm objects using NSPredicate.
This doesn't work
RLMResults *activtyResults = [[[self getActivitySource]activities] objectsWhere:#"ID ==[c] '%#'",activityID];
activtyResults is nil
This works:
for (RealmActivity *activity in [[self getActivitySource]activities]){
if ([activity.ID isEqualToString:activityID]) {
return activity;
}
}
The activityID is a uuid: f20f6217-9cb6-4fe1-9333-8956d1252112
Why the predicate format #"ID ==[c] '%#'" doesn't work here ?Does it have anything to do with the property name being ID ?
A predicate of ID == %# would be equivalent to the imperative code you shared.
I'd expect the predicate you used to generate an error, rather than silently returning nil, due to the extraneous single quotes it contains. The lack of error combined with the nil result you're seeing suggests to me that the object you're invoking -objectsWhere: on is likely nil.

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.

NSPredicate crash on CONTAINS?

I'm trying to do a simple predicate filter on an array of objects.
The objects in the array have 2 properties, displayValue and value. I am trying to filter based on a search string and I get a crash.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"displayValue CONTAINS[cd] %#", searchString];
NSArray *results = [_data filteredArrayUsingPredicate:pred];
what exactly is incorrect about this format that it causes a Can't use in/contains operator with collection 100 (not a collection) crash?
I was able to reproduce your problem. This happens if the displayValue of one of the objects
is not a NSString, but some different type.
From your error message, I assume that you assigned an NSNumber, for example
obj.displayValue = #100;
somewhere in your code. The "CONTAINS" predicate works only with strings, so you must assign
only string values to the property.
Therefore, you should define the type of the property as
NSString * instead of id, and check the assignments to that property.
If you really need to keep the id type and store different kinds of objects in that property,
then you cannot use the "CONTAINS" operator in the predicate. A direct comparison
with #"displayValue == %#" would work, however.
UPDATE: As a workaround, you could use the description method, which converts any object
to a string, in particular it converts a NSNumber to its string representation. So the following could work:
[NSPredicate predicateWithFormat:#"displayValue.description CONTAINS[cd] %#", searchString];
The drawback is that the exact description format is not documented.
Another solution could be to use a block-based predicate, where you can check the type
of each object and perform the appropriate comparison.

Error when trying to sort array using predicates

I'm struggeling with an error occurring when trying to populate an array with the filtered results of another array.
I've defined a global array named allArray in the .h-file, this array is containing about 100 objects. Then, I want the user to be able to search for a specific object, and I've tried to develop it using predicates:
-(IBAction)searchChanged:(id)sender {
//The searchfield's value has been changed.
NSString *searchString = searchField.text;
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:#"self CONTAINS[c] %#", searchString];
NSMutableArray *tempSearchArray = [allArray filterUsingPredicate:searchPredicate];
[filteredArray removeAllObjects];
[filteredArray addObjectsFromArray:tempSearchArray];
}
I end up getting an error when I create tempSearchArray.
Initializing 'NSMutableArray *__strong' with an expression of
incompatible type 'void'
filterUsingPredicate doesn't return an array, it returns nothing(void).
From the description:
"Evaluates a given predicate against the array’s content and leaves only objects that match"
You should instead use:
filteredArrayUsingPredicate
As the Docs will tell you, filterUsingPredicate has a void return value.
See here:
NSMutableArray Class reference
That means that you cannot assign that return value to another array.
You need to use this method on the original array, along the lines of
[allArray filterUsingPredicate:somePredicate];
arrArray will be stripped of any elements that dont match the predicate.
Now proceed with these results as you wish.
Have Fun
filterUsingPredicate returns a void and not an array. You might want to consider using a filteredArrayUsingPredicate instead

Resources