Reputation: 3965
I have an NSArray of objects, and those objects have 10 properties. I would like to do a text search of those objects.
I know how to search 1 property at a time, but is there an easy way to search ALL properties at once?
Here is a list of properties that my objects have:
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * phone;
@property (nonatomic, retain) NSString * secondaryPhone;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * email;
@property (nonatomic, retain) NSString * url;
@property (nonatomic, retain) NSString * category;
@property (nonatomic, retain) NSString * specialty;
@property (nonatomic, retain) NSString * notes;
@property (nonatomic, retain) NSString * guid;
If I search for "doctor", I would like to see all results where 1 or more of these properties has the word "doctor" in it. For example, if 1 object has a category of "doctor", and another object has an email address of "[email protected]", they should both show up in the results.
Upvotes: 3
Views: 11478
Reputation: 483
Instead of hardcoding each property name individually, you could get an array of the class's property names: List of class properties in Objective-C, (assuming they were all strings, or you could check if each property's type is of class NSString
but I'm not sure how to do this)
and then on each of the objects you'd like to search, you could iterate through each of the object's properties and inspect the value on each:
id objectValue = [object valueForKey:[NSString stringWithUTF8String:propertyName]];
// let's say the property is a string
NSString *objectValueString = (NSString *)objectValue;
Then you could check if the property matches your searchTerm with something like:
BOOL propertyValueMatchesSearchTerm = [objectValueString rangeOfString:mySearchTermString].location != NSNotFound;
if (propertyValueMatchesSearchTerm) {
// add object to search results array
}
Upvotes: 0
Reputation: 318794
Add a matches:
method to your class:
- (BOOL)matches:(NSString *)term {
if ([self.name rangeOfString:term options:NSCaseInsensitiveSearch| NSDiacriticInsensitiveSearch].location != NSNotFound) {
return YES;
} else if ([self.phone rangeOfString:term options:NSCaseInsensitiveSearch| NSDiacriticInsensitiveSearch].location != NSNotFound) {
return YES;
} else if (...) { // repeat for all of the properties
return YES;
}
return NO;
}
Now you can iterate over your objects checking each one:
NSArray *peopleArray = ... // the array of objects
NSString *someTerm = ... // the search term
NSMutableArray *matches = [NSMutableArray array];
for (id person in peopleArray) {
if ([person matches:someTerm]) {
[matches addObject:person];
}
}
Upvotes: 0
Reputation: 4097
NSString *searchTerm = @"search this";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF LIKE[cd] %@", searchTerm];
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
If there is a specific property you can change the predicate to:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.propertyName LIKE[cd] %@", searchTerm];
To search all properties, you will have to bind them together with a logical operator
NSString *query = @"blah";
NSPredicate *predicateName = [NSPredicate predicateWithFormat:@"name contains[cd] %@", query];
NSPredicate *predicatePhone = [NSPredicate predicateWithFormat:@"phone contains[cd] %@", query];
NSPredicate *predicateSecondaryPhone = [NSPredicate predicateWithFormat:@"secondaryPhone contains[cd] %@", query];
NSArray *subPredicates = [NSArray arrayWithObjects:predicateName, predicatePhone, predicateSecondaryPhone, nil];
NSCompoundPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
Upvotes: 14