iOS wrong range returned while using rangeOfMisspllledWordInString function of UITextChec

ashwinr87

macrumors member
Original poster
Mar 9, 2011
81
0
Hi,

I am using this code to spell check the text I type in my UITextView.
My code below is similar to the one used in the Spell Check and Word Completion section of apple documentation

Code:
- (IBAction)didPressButton:(id)sender
    {
        NSInteger currentOffset = 0;
        NSRange currentRange = NSMakeRange(0, 0);
        NSString *theText = self.textView.text;
        NSRange stringRange = NSMakeRange(0, theText.length-1);
        NSArray *guesses;
        BOOL done = NO;
        NSString *theLanguage = [[UITextChecker availableLanguages] objectAtIndex:0];
    
    if (!theLanguage)
        
        theLanguage = @"en_US";
    
    while (!done)
    {
        currentRange = [self.checker rangeOfMisspelledWordInString:theText range:stringRange
                                                        startingAt:currentOffset wrap:NO language:theLanguage];
        NSLog(@"currentRange : %d", currentRange.location);
        
        if (currentRange.location == NSNotFound)
        {
            done = YES;
            continue;
        }
        
        guesses = [self.checker guessesForWordRange:currentRange inString:theText
                                           language:theLanguage];
        
        NSLog(@"Word misspelled is %@", [theText substringWithRange:currentRange]);
        NSLog(@"Possible replacements are %@", guesses);
        
        self.textView.text = [self.textView.text stringByReplacingCharactersInRange:currentRange
                                                                         withString:[guesses objectAtIndex:0]];
        currentOffset = currentOffset + (currentRange.length-1);
        NSLog(@"currentOffset : %d", currentOffset);
    }
    }
In my UITextChecker, I type in "Thiis is a speell check"

When I click the button, it calls the didPressButton function and it starts the process of spell checking the string in the UITextView. when it reaches "speell" it throws out a wrong range and it crashes the application. I logged the range and when I had a breakpoint before the if (currentRange ... ) code. looking at the log output, I saw that it returns a wrong range after it does the spell check for "speell".

The app crashes on the line "self.textView.text = [self.textView.text stringByReplacingCharactersInRange:currentRange withString:[guesses objectAtIndex:0]];"


I am unable to figure out what is going wrong.
It would be really great if someone could help me figure this out.
 
Last edited:

ashwinr87

macrumors member
Original poster
Mar 9, 2011
81
0
What makes you think the range is wrong?

When the app crashes, what is the run-time error message? What line of code is causing the crash? Details, please.
I logged the range and when I had a breakpoint before the if (currentRange ... ) code. looking at the log output, I saw that it returns a wrong range after it does the spell check for "speell".

The app crashes on the line "self.textView.text = [self.textView.text stringByReplacingCharactersInRange:currentRange withString:[guesses objectAtIndex:0]];"

I also edited my question with the details.
 

chown33

Moderator
Staff member
Aug 9, 2009
8,452
4,452
Pale blue comma
I logged the range and when I had a breakpoint before the if (currentRange ... ) code. looking at the log output, I saw that it returns a wrong range after it does the spell check for "speell".

The app crashes on the line "self.textView.text = [self.textView.text stringByReplacingCharactersInRange:currentRange withString:[guesses objectAtIndex:0]];"

I also edited my question with the details.
Dejo was asking you to post the actual range values you observed that caused you to conclude it was wrong. Debugging, especially debugging by asking for advice, boils down to "Show your evidence". That means show the actual log output, show the actual values of the range, etc.

Don't just post your conclusions (e.g. "the range is wrong"). Post the evidence that leads to the conclusion (e.g. "the range location is 982, even though the string is only 20 chars").


Your code has a logic flaw. You do this:
Code:
        NSString *theText = self.textView.text;
but you don't ever assign a new value to theText, even though you also do this in the loop:
Code:
        currentRange = [self.checker rangeOfMisspelledWordInString:[COLOR="Red"]theText[/COLOR] range:stringRange
                                                        startingAt:currentOffset wrap:NO language:theLanguage];

 ...
        self.textView.text = [[COLOR="red"]self.textView.text[/COLOR] stringByReplacingCharactersInRange:currentRange
                                                                         withString:[guesses objectAtIndex:0]];
After the first replacement occurs, theText and self.textView.text are no longer the same string. So at best you're doing replacement on the wrong text, and at worst, you're doing a spell-check with an NSString you don't own.


Your code doesn't account for the possibility that guesses has no object at index 0 (empty guesses). It always assumes there is at least 1 guess.


Finally, this:
Code:
        if (currentRange.location == NSNotFound)
        {
            done = YES;
            continue;
        }
suggests you would benefit from reviewing how the break keyword works in a loop.
 

ashwinr87

macrumors member
Original poster
Mar 9, 2011
81
0
Dejo was asking you to post the actual range values you observed that caused you to conclude it was wrong. Debugging, especially debugging by asking for advice, boils down to "Show your evidence". That means show the actual log output, show the actual values of the range, etc.

Don't just post your conclusions (e.g. "the range is wrong"). Post the evidence that leads to the conclusion (e.g. "the range location is 982, even though the string is only 20 chars").


Your code has a logic flaw. You do this:
Code:
        NSString *theText = self.textView.text;
but you don't ever assign a new value to theText, even though you also do this in the loop:
Code:
        currentRange = [self.checker rangeOfMisspelledWordInString:[COLOR="Red"]theText[/COLOR] range:stringRange
                                                        startingAt:currentOffset wrap:NO language:theLanguage];

 ...
        self.textView.text = [[COLOR="red"]self.textView.text[/COLOR] stringByReplacingCharactersInRange:currentRange
                                                                         withString:[guesses objectAtIndex:0]];
After the first replacement occurs, theText and self.textView.text are no longer the same string. So at best you're doing replacement on the wrong text, and at worst, you're doing a spell-check with an NSString you don't own.


Your code doesn't account for the possibility that guesses has no object at index 0 (empty guesses). It always assumes there is at least 1 guess.


Finally, this:
Code:
        if (currentRange.location == NSNotFound)
        {
            done = YES;
            continue;
        }
suggests you would benefit from reviewing how the break keyword works in a loop.
Thank you.. I also figured out that I was doing the same mistakes..