Reputation: 1129
I apologize if this is a repeat, but I honestly have done my best to research this and haven't come up with much.
I'm making an iPad reference app that will make several large textbooks searchable (maybe 3-4k pages in total). It's a fairly simple idea: the user can choose any combination of texts to search, put in his term, and the app will find those terms in all the texts and return them, indexed in a table view.
The view controller has a series of switches, the value of which get read by a method into an NSSet and passed to the search controller. That part works.
I have a SearchController class which the view controller instantiates and calls a method on:
-(void)performSearchWithString:(NSString *)searchString andTexts:(NSSet *)texts
{
for (id book in texts) {
if ([book isEqual:kBook1]){
NSError *error = nil;
NSURL *url = [[NSBundle mainBundle] URLForResource:@"neiJing" withExtension:@"txt"];
NSString *text = [NSString stringWithContentsOfURL:url encoding:NSStringEncodingConversionAllowLossy error:&error];
[text enumerateSubstringsInRange:NSMakeRange(0, [text length])
options:NSStringEnumerationByWords
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
NSRange found = [substring rangeOfString:text];
if (found.location != NSNotFound) {
NSLog(@"%@", substring);
} else {
NSLog(@"Not found");
}
}];
}
I seem to have succeeded in enumerating through every word in all the texts, but no return values are found so I just get a never-ending stream of "Not found".
I inserted a test phrase into each text that I know for certain to be there, but it's not coming up.
I have a feeling I'm going about this all wrong. Even if I made this work, the performance hit might be too big for a useable app...I'm still trying to wrap my head around blocks, too. I just haven't found any ready-baked solutions out there for searching large volumes of text and picking out results. If anyone has any hints or references to an open-source library that I might adapt, I would be very grateful.
Upvotes: 3
Views: 262
Reputation: 42588
I don't think the block of code is what you want. It loops through each word in the text and you want to find all the search strings. Here is a loop that sets a new search range based on the last successful match.
-(void)performSearchWithString:(NSString *)searchString andTexts:(NSSet *)texts
{
for (id book in texts) {
if ([book isEqual:kBook1]){
NSError *error = nil;
NSURL *url = [[NSBundle mainBundle] URLForResource:@"neiJing" withExtension:@"txt"];
NSString *text = [NSString stringWithContentsOfURL:url encoding:NSStringEncodingConversionAllowLossy error:&error];
NSRange searchRange = NSMakeRange(0, [text length]);
NSRange match = [text rangeOfString:searchString options:0 range:searchRange];
while (match.location != NSNotFound) {
// match is the range of the current successful match
NSLog(@"matching range -- %@", NSStringFromRange(match));
NSUInteger locationOfNextSearchRange = NSMaxRange(match);
searchRange = NSMakeRange(locationOfNextSearchRange, [text length] - locationOfNextSearchRange);
match = [text rangeOfString:searchString options:0 range:searchRange];
}
}
}
Upvotes: 1
Reputation: 62686
It looks like you're searching for the whole text inside of each substring passed to the block. This line is the problem (and causes a retain cycle):
NSRange found = [substring rangeOfString:text];
The code needs to look for something it can find:
NSString *findMe = @"A string we expect to find";
[text enumerateSubstringsInRange:NSMakeRange(0, [text length])
options:NSStringEnumerationByWords
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
if ([findMe isEqualToString:substring] ) {
NSLog(@"Found %@", substring);
} else {
NSLog(@"Not found");
}
}];
Upvotes: 2