Spotlight uses NSScanner to parse search strings, eliminating most crashes resulting from unusual search strings.

CQTexperiment
matthewleon 2008-02-13 18:47:24 +00:00
parent f64ebf597f
commit 62c446160c
3 changed files with 56 additions and 39 deletions

View File

@ -87,5 +87,11 @@ static NSDictionary * tags;
return self; return self;
} }
- (void)dealloc
{
[length release];
[super dealloc];
}
@synthesize length; @synthesize length;
@end @end

View File

@ -11,6 +11,9 @@
#import "PlaylistLoader.h" #import "PlaylistLoader.h"
#import "SpotlightPlaylistEntry.h" #import "SpotlightPlaylistEntry.h"
// Minimum length of a search string (searching for very small strings gets ugly)
#define MINIMUM_SEARCH_STRING_LENGTH 3
// Store a class predicate for searching for music // Store a class predicate for searching for music
static NSPredicate * musicOnlyPredicate = nil; static NSPredicate * musicOnlyPredicate = nil;
@ -45,12 +48,10 @@ static NSPredicate * musicOnlyPredicate = nil;
- (void)performSearch - (void)performSearch
{ {
// Process the search string into a compound predicate NSPredicate *searchPredicate;
NSPredicate *searchPredicate = [self processSearchString]; // Process the search string into a compound predicate. If Nil is returned do nothing
if(searchPredicate = [self processSearchString])
// Set scope to contents of pathControl {
[self.query setSearchScopes:[NSArray arrayWithObjects:pathControl.URL, nil]];
// spotlightPredicate, which is what will finally be used for the spotlight search // spotlightPredicate, which is what will finally be used for the spotlight search
// is the union of the (potentially) compound searchPredicate and the static // is the union of the (potentially) compound searchPredicate and the static
// musicOnlyPredicate // musicOnlyPredicate
@ -59,32 +60,39 @@ static NSPredicate * musicOnlyPredicate = nil;
[NSArray arrayWithObjects: musicOnlyPredicate, [NSArray arrayWithObjects: musicOnlyPredicate,
searchPredicate, searchPredicate,
nil]]; nil]];
// Only preform a new search if the predicate has changed
if(![self.query.predicate isEqual:spotlightPredicate])
{
if([self.query isStarted]) if([self.query isStarted])
[self.query stopQuery]; [self.query stopQuery];
self.query.predicate = spotlightPredicate; self.query.predicate = spotlightPredicate;
// Set scope to contents of pathControl
self.query.searchScopes = [NSArray arrayWithObjects:pathControl.URL, nil];
[self.query startQuery]; [self.query startQuery];
NSLog(@"Started query: %@", [self.query.predicate description], [[self.query class]description]); NSLog(@"Started query: %@", [self.query.predicate description]);
}
}
} }
- (NSPredicate *)processSearchString - (NSPredicate *)processSearchString
{ {
// a somewhat dumb way to collapse the whitespace in searchString NSMutableArray *searchComponents = [NSMutableArray arrayWithCapacity:10];
// TODO: write a more elegant way of accomplishing this
NSString * compareString = [self.searchString
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSString * collapsedString = [compareString stringByReplacingOccurrencesOfString:@" " NSScanner *scanner = [NSScanner scannerWithString:self.searchString];
withString:@" "];
while (![collapsedString isEqualToString:compareString]) while (![scanner isAtEnd])
{ {
compareString = [collapsedString copy]; NSString *scannedString;
collapsedString = [compareString stringByReplacingOccurrencesOfString:@" " if ([scanner scanUpToString:@" " intoString:&scannedString])
withString:@" "]; {
// don't add tiny strings in... They're make the system go nuts
// TODO: Maybe consider a better solution to the issue?
if ([scannedString length] >= MINIMUM_SEARCH_STRING_LENGTH)
{
[searchComponents addObject:scannedString];
}
}
} }
// break the string up into an array of each word
NSArray * searchComponents = [collapsedString
componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// create an array of all the predicates to join together // create an array of all the predicates to join together
NSMutableArray * subpredicates = [NSMutableArray NSMutableArray * subpredicates = [NSMutableArray
@ -110,8 +118,9 @@ static NSPredicate * musicOnlyPredicate = nil;
//TODO: Ability to search only artist, albums, etc. //TODO: Ability to search only artist, albums, etc.
[subpredicates addObject: predicate]; [subpredicates addObject: predicate];
} }
if ([subpredicates count] == 0)
if ([subpredicates count] == 1) return Nil;
else if ([subpredicates count] == 1)
return [subpredicates objectAtIndex: 0]; return [subpredicates objectAtIndex: 0];
// Create a compound predicate from subPredicates // Create a compound predicate from subPredicates
@ -161,7 +170,9 @@ replacementObjectForResultObject:(NSMetadataItem*)result
@synthesize searchString; @synthesize searchString;
- (void)setSearchString:(NSString *)aString - (void)setSearchString:(NSString *)aString
{ {
if (searchString != aString) { // Make sure the string is changed
if (searchString != aString)
{
searchString = [aString copy]; searchString = [aString copy];
[self performSearch]; [self performSearch];
} }