Re: wordRangeForRange implememtation
Re: wordRangeForRange implememtation
- Subject: Re: wordRangeForRange implememtation
- From: Ali Ozer <email@hidden>
- Date: Sat, 10 May 2008 19:42:11 -0700
There are a number of problems in this code...
- (NSRange)wordRangeForRange:(NSRange)range{
NSString *string = [NSString stringWithString:[[self string]
substringWithRange:range]];
Why do you make yet another copy of the string; you already have the
substring? Maybe you meant to make a mutable copy?
if([string hasPrefix:@" "]){
[string stringByReplacingCharactersInRange:NSMakeRange(0, 1)
withString:@""];
"string" is not mutable, but you are mutating it here. You should be
getting a compiler warning. Also, don't you want to check for other
"white space" characters, such as tab, etc?
range.location++;
You probably would also want to do range.length-- here; otherwise your
range now pokes outside of the original range that was passed in.
}
NSString *op = [NSString stringWithString:[self string]];
Since you said this is in an NSTextView subclass, [self string] is the
whole contents of the string; you are making a copy of it, which could
be wasteful.
int length = range.location;
Best to use NSInteger here, for longer-lasting code (but "int" isn't
wrong, under 32-bit)
int finished = 0;
BOOL would be a better choice in general (but again, "int" isn't wrong)
while(finished != 1){ //2
if([op substringWithRange:NSMakeRange(length, 1)] == @" "){
You can compare strings for equality with ==; use ieEqual:
finished = 1;
}else{
NSLog([op substringWithRange:NSMakeRange(length, 1)]); //1
Don't NSLog a string directly; if your string happens to contain "%",
you will get into trouble (and may crash). Instead do NSLog(@"%@",
str).
length++;
}
}
range.length = length;
return range;
}
That was sort of a "micro" commentary of your code; but I haven't done
an overall examination to see whether these fixes would fix it. To
extract a word range from a string, it may be easier to use something
like NSScanner:
// Defining the words
NSCharacterSet *validWordSet = [NSCharacterSet
alphanumericCharacterSet]; // Or however you want to define words
NSCharacterSet *wordBreakSet = [validWordSet invertedSet];
// Set up a scanner
NSScanner *scanner = [NSScanner scannerWithString:yourString];
[scanner setCharactersToBeSkipped:nil]; // We will manage skipping
ourselves (since we need to find the beginning of the word)
NSString *word = nil;
NSRange range;
[scanner scanCharactersFromSet:wordBreakSet intoString:nil]; // Skip
range.location = [scanner scanLocation]; // Beginning of the word
if ([scanner scanCharactersFromSet:validWordSet intoString:&word])
{ // Scan the word; if successful, word will contain it, and range
will contain the range
range.length = [scanner scanLocation] - range.location;
}
But better yet, NSAttributeString in AppKit has doubleClickAtIndex:
and nextWordFromIndex:forward:. These are more for text editing
purposes, not actually detecting words, but they may very well be good
enough for your usage (at least as good as the above algorithm).
Or you can use CFStringTokenizer, which does a much better job of
actually trying to recognize words in different languages.
Ali
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden