Reputation: 7778
EDIT: I'm adding a new rough table model for comment. Is this what you had in mind?
I'm still trying to work out a search filter for a core data set. I got stuck here, so I'm approaching the problem differently.
First, what I'm trying to do is the following:
Iterate through all objects (NSManageObject *object in tableViewModel.items)
Extract all the subentity objects for each 'object' and validate against search term.
If the search term does exist in the subentity, then add 'object' to 'autoSearchResults' (if it doesn't already exist there)
My code is as follows:
NSLog(@"%s", __FUNCTION__);
NSMutableArray *startArray = [NSMutableArray array];
NSMutableArray *filteredArray = [NSMutableArray array];
for (NSManagedObject *object in tableViewModel.items)
{
NSLog(@"1 ");
NSSet *set1 = [object valueForKeyPath:@"people.name"];
NSString *str1 = [[set1 allObjects] componentsJoinedByString:@", "];
peopleSet = str1;
NSLog (@"peopleSet is %@ ", peopleSet);
NSLog(@"2 ");
NSSet *set2 = [object valueForKeyPath:@"place.name"];
NSString *str2 = [[set2 allObjects] componentsJoinedByString:@", "];
placeSet = str2;
NSLog(@"3 ");
NSSet *set3 = [object valueForKeyPath:@"keyword.name"];
NSString *str3 = [[set3 allObjects] componentsJoinedByString:@", "];
keywordSet = str3;
NSLog(@"4 ");
NSSet *set4 = [object valueForKeyPath:@"type.name"];
NSString *str4 = [[set4 allObjects] componentsJoinedByString:@", "];
typeSet = str4;
NSLog(@"5 ");
NSSet *set5 = [object valueForKeyPath:@"symbol.name"];
NSString *str5 = [[set5 allObjects] componentsJoinedByString:@", "];
symbolSet = str5;
NSLog(@"6 ");
NSLog (@"searchText is: %@ ", searchText);
myPredicate = [NSPredicate predicateWithFormat:@"(peopleSet contains[cd] %@) || (placeSet contains[cd] %@) || (keywordSet contains[cd] %@) || (typeSet contains[cd] %@) || (symbolSet contains[cd] %@)", searchText, searchText, searchText, searchText, searchText ];
NSLog(@"7 ");
if (myPredicate) {
[startArray addObject:object];
NSLog (@"startArray.count is %i ", startArray.count);
}
NSLog(@"8 ");
NSLog (@"startArray.count is %i ", startArray.count);
/*
if (startArray.count == 0)
{
NSLog(@"0");
} else {
NSLog(@"9 ");
[filteredArray addObject: startArray];
NSLog(@"10 ");
[startArray removeAllObjects];
NSLog(@"11 ");
}
*/
}
//autoSearchResults = filteredArray;
return autoSearchResults;
}
In my testing, I have 3 objects, one with the person.name "me", one with "you", and one with "Mother". All the other fields are blank in all objects.
Right now, I'm stopping to see how many objects are selected for each search. Essentially, the searchText is found but ignored. That is, the routine sees that the searchText contains "me" for example, but still adds an Object where the actual text is "You".
I would appreciate any help.. If it would help to reduce this example, please let me know..
Upvotes: 0
Views: 1370
Reputation: 31782
The most egregiously wrong thing about this code is that you're not actually using the predicate you create. In order to test an object against a predicate, call evaluateWithObject:
on the predicate, passing in the object to test.
But that still won't work, because it doesn't know what "peopleSet" and all those other strings are: you can't use a local variable as if it were a keypath.
Finally, this structure doesn't really take advantage of the power of predicates; you're using a predicate like a regex. To actually filter an object collection, use a method such as filteredSetUsingPredicate:
on the collection itself instead of testing every object.
Of course, this will require you to create a transient property on your managed object model to store the concatenated list of names, but if you do that correctly, you'll see a performance boost when doing this kind of filtering.
Upvotes: 2