Spotlight uses NSScanner to parse search strings, eliminating most crashes resulting from unusual search strings.
parent
f64ebf597f
commit
62c446160c
|
@ -87,5 +87,11 @@ static NSDictionary * tags;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[length release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
@synthesize length;
|
@synthesize length;
|
||||||
@end
|
@end
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue