I have an array called deletedDepartments which contains NSObjects called DeletedObject. A DeletedObject only has a field called deletedID. This array is generated from a mapping with RestKit.
Now, I want to search within CoreDate for Department objects where their id is within the deletedDepartments array.
If I do
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"id IN %#", deletedDepartments ]];
This won't work because deletedDepartments is not a NSArray made of NSNumber, but of NSObject which contains the NSNumber I want to compare. How can I achieve such thing without creating another array made from iterating over the deletedDepartments and selecting only the deletedID?
Change your predicate to the following :
[NSPredicate predicateWithFormat:#"deletedID IN %#", [deletedDepartments valueForKey:#"deletedID"]]
This will create an array of your deletedId's, and evaluate each object using the deletedId property. While, yes, this does internally iterate over the array to create a new one, that's the best you can do unless the NSObjects in deletedDepartments are of the same class as the model objects that your are fetching.
Related
I have actually a core data entity called Show and for every show I have a relation ship called Schedule that contains an attribute called schedules which is an array.
What I want to do is to create a Predicate that checks for a given show's schedule if it has more than 1 item.
To do That I tried Two solutions :
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"schedule.schedules > 1];
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"schedule.schedules.#count > 1];
But None of them would work.
NB : schedules attribute is an stored in my Core Data as Transformable and declared as an id variable.
A transformable attribute is stored as binary data, and it isn't unpacked until the container entity is loaded into memory. So, you can't use any kind of predicate based on a transformable attribute in a fetch. It will only work to filter the results of the fetch.
Cheap solution is to store a simple integer attribute with the count and use that.
Better solution is likely to add / change your entities so you use a relationship instead of a transformable.
Did you try this?
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"#count.schedule.schedules > 1];
I have 3 core data entities.
MenuItems, Items, ItemLangs.
All entities has iItemId attribute. The user need to search using sItemName which can be found in the ItemLangs.
The UITableView contains array of MenuItems.
I have tried filteredArrayUsingPredicate but my predicate is not right. Do I need to loop through the array of MenuItems first before I can filter the array?
Here is my predicate:
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"sItemName LIKE %#", searchText];
May I know how can I use this to filter the array of MenuItems that I have?
Thank you!
What you need is a predicate like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"sItemName CONTAINS[cd] %#", searchText];
[cd] stands for case insensitiveness.
Alternately, if you like "LIKE", refer to this answer.
UPDATE:
You should also look at the data item you want to fetch - sItemName in your case. Through debugger, inspect what object does your data source array return? I am referring to the array you want to apply the above predicate to. Maybe there is some keypath hierarchy involved in getting through towards sItemName, in which case you need to use dot notation, such as Items.ItemLangs.sItemName.
Refer following links, it may help you:
1) How to implement SearchBar and search display controller in tableview in xib
2) first attempt at synamic filtering a search array
3) http://www.appcoda.com/search-bar-tutorial-ios7/
4) http://www.raywenderlich.com/16873/how-to-add-search-into-a-table-view
i'm working with core data and i've two tables
List
ListItems
ListItems has a relationship named "parentlist" with destination set to "List"
I'm trying to query the ListItems for all the listItems whoes parent is X (List object)
i've tried this approach but it's not working
List* myList; // Initialized form other views
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"List == %#",myList]];
If you have an inverse relationship listItems (as Apple recommends) you can use just:
myList.listItems
There are two problems in your code: In the predicate you have to use the relationship ("parentList"),
not the target entity ("List"). And you should not mix string formatting with
predicate formatting.
To get all ListItems related to the given list, the predicate would be
List* myList = ...;
NSPredicate *pred = [NSPredicate predicateWithFormat:#"parentList == %#", myList];
I'm assuming you're looking for something other than simply accessing the listItems through the list? If so :
comparing objects in core data doesn't really work that way.
You could do this in one of two ways,
Easy : Assign the lists a GUID on creation using :
[[NSProcessInfo processInfo] globallyUniqueString]
and use this for comparing two lists.
Harder : implement a comparison function on the objects by overriding compare and compare the objects in a way that makes sense to you.
- (NSComparisonResult) compare : (List *) other;
Then create a NSPredicate using blocks.
You could also use a GUID and use it in the compare function, thus allowing you to expand on this later.
I have an NSArray of objects each of with contain a "key" field
I have another NSArray with nested NSArrays grouping those objects by a different field "group by field" for instance a display name (alphabetic grouping)
For instance
#interface MyObject
#property (nonatomic) int key;
#property (nonatomic,strong) NSString *groupByKey;
#end
NSArray *aBounchOfObjectsInAFlatList = #[obj1,obj2,obj3....];
NSArray *groupByArrayOfObjects = #[#[obj1_tag,obj2_tag],#[objn_tag,objk_tag]....];
Important to note that obj1 != obj1_tag - they only share values of "groupByKey" and/or "key".
I would like to find the index of each obj_tag where (obj_tag.key == obj.key) from the flat array.
Now I am running 2 loops and saving the counter values - creating index paths for the matches.
I assume there is a clear way using NSPredicates to create an array of NSIndexPaths for the corresponding objects but I am not clear how to do this
NSPredicate is just a predicate and nothing more. It is applied to some object and
yields YES or NO. A predicate can be used for filtering an array, but since the predicate itself is applied to each single array element, it does not "know" the location
(or index) of the object being tested.
Therefore a NSPredicate cannot create an array of NSIndexPaths.
The NSArray method indexOfObjectPassingTest: can be useful to find the location
of an object in an array, but even that method has to loop over all array elements
to find the object. So it might help to make the code shorter or better readable, but
it does not change the performance.
If groupByArrayOfObjects is really large, then you can create a mapping (an NSDictionary) from each key to the corresponding index path first. This requires only one enumeration of the (nested) array. Then you can use this mapping to get
the index path for each element in the other array aBounchOfObjectsInAFlatList.
I have a fairly large number of NSManagedObjects in an NSArray and need to check whether do any of them have the same value for a property. The obvious way is nested for loops however it will take ages to go through all of them as there are about a 1000 objects in the array.
for (NSManagedObject *object in array) {
for (NSManagedObject *secondObject in array {
if ([[object valueForKey:#"key"] isEqualTo:[secondObject valueForKey:#"key"]] &&
object != secondObject) {
NSLog(#"Sharing a property");
}
}
}
Any better way to do this? If there are 1000 objects that accounts to 1 000 000 comparisons, that might take some time.
You could use an NSDictionary. Each entry would be made from the following pair:
key would be equal to the selected NSManagedObjects attribute
value would be an NSArray of NSManagedObjects, that share this attribute's value
Get the list of key values for the objects in the array, then turn that into a set. If the size of the set is the same as that of the original array, there are no matches.
If you need to know which objects match, use a dictionary to create a multiset -- each key has an array of the objects as its value.
Creating your own keyed set class is also an option.
You can sort the array according to the values of that property.
Then a single loop over
the array is sufficient to find objects sharing the same value of the property.