开发者

Having trouble with UITextChecker - Xcode/iPhone

开发者 https://www.devze.com 2023-02-18 11:14 出处:网络
I\'ve been trying to use UITextChecker to see if a word inside a string i开发者_JAVA技巧s, in fact, actually a word. I\'ve pieced the code together using examples I\'ve found online, but I don\'t real

I've been trying to use UITextChecker to see if a word inside a string i开发者_JAVA技巧s, in fact, actually a word. I've pieced the code together using examples I've found online, but I don't really understand it, and it's a bit above my level. Can anyone help me figure out how to check if a word in a string is really a word? I'm still learning all of this so thanks a ton!

-(IBAction)pushButton:(id)sender{
label.text = textField.text;
NSString * currentWord;
currentWord = label.text;
NSRange range = NSMakeRange(0, 0);
range = [textChecker rangeOfMisspelledWordInString:[currentWord lowercaseString] 
                                             range:NSMakeRange(0, [currentWord length]) 
                                        startingAt:0 
                                              wrap:NO 
                                          language:@"en_US"];
if (range.location == NSNotFound) {
    NSLog(@"Word found");
}
    else {
        NSLog(@"Word not found");
    }

}

UPDATE: I'm still having trouble with this, as my log is showing "Word not found" no matter what I put in the textfield. I wanted to post my .h file as well to see if something is incorrect. Also here is a link to where I received the original code, in case that helps. Thanks again.

 #import <UIKit/UIKit.h>
#import <UIKit/UITextChecker.h>

@interface CheckIfWordViewController : UIViewController {
    IBOutlet UILabel * label;
    IBOutlet UITextField * textField;
    IBOutlet UIButton * button;
    UITextChecker * textChecker;
}
@property (retain, nonatomic) UITextChecker * textChecker;
@property (retain, nonatomic) UIButton * button;
@property (retain, nonatomic) UILabel * label;
@property (retain, nonatomic) UITextField * textField;


-(IBAction)pushButton:(id)sender;

@end


I got caught out by UITextChecker always returning NSNotFound even for misspelled words because I was feeding it CAPs only words. A slight problem for rookies solved by submitting [currentWord lowercaseString]. I also discovered from researching this that words over 25 characters will also return NSNotFound irrespective of incorrect spelling.


Your code looks like it is passing one word to rangeOfMisspelledWordInString - I think you want to use the whole string and use the returned NSRange to identify which word in particular UITextChecker thinks is misspelled. So instead of currentWord, pass the whole string. If nothing is misspelled you get range.location == NSNotFound as you worked out.

A word check is only as good as the dictionary you check against. I believe it was Don Knuth who devised this method for checking words:

  1. Get dictionary
  2. Create copy of dictionary with all entries sorted so that sorted word index matches unsorted word index
  3. Sort candidate word
  4. Find sorted candidate word in sorted dictionary
  5. Index (and there may be multiples) of match is your word.

In your case you only care if there are zero matches or otherwise. If there is at least one match you have a valid word.

I do not know exactly what dictionaries UITextChecker uses but nothing will annoy people more than rejecting a correct word... especially if they consider their word a bit obscure and themselves clever for using it. Using an all-encompassing dictionary like the official Scrabble reference will avoid that problem.


Your code looks correct, I guess from your question you want it explained?

    label.text = textField.text;

This line takes the text entered in textField (which is presumably a UITextField) and assigns it to the text property of label (which is presumably a UILabel). It has nothing to do with the spell checking per se.

    NSString * currentWord;
    currentWord = label.text;

This copies the text string back out of the label's text property.

    NSRange range = NSMakeRange(0, 0);

This declares an NSRange struct, and initializes it to an empty value. Not really necessary, since the next line will change it anyway.

    range = [textChecker rangeOfMisspelledWordInString:[currentWord lowercaseString] 
                                                 range:NSMakeRange(0, [currentWord length]) 
                                            startingAt:0 
                                                  wrap:NO 
                                              language:@"en_US"];

This is the line that actually does the work.

  • You're searching for misspelled words in the text string from earlier. It lowercases it for good measure, I don't know if that's strictly necessary.
  • range:NSMakeRange(0, [currentWord length]) specifies that the entire string (from character 0 to the length of the string) should be searched.
  • startingAt:0 specifies that it should start from the beginning of the range. The use of this would be in a loop, after finding the first misspelled word you'd tell it to start after the end of the word to find another.
  • wrap:NO tells it not to start over from the beginning of the range if a misspelled word. Not that that matters here.
  • `language:@"en_US" tells it to use the built-in US English dictionary.

There doesn't seem to be any way to specify a custom dictionary, BTW.

    if (range.location == NSNotFound) {
        NSLog(@"Word found");
    }
    else {
        NSLog(@"Word not found");
    }

This just checks the result. If a misspelled word were found, range.location would be the start of the word and range.length would be the length. If all the words are spelled correctly, range.location will be NSNotFound and range.length will be 0.


Where are you allocating the UITextChecker? In the controller's init method, I assume? Just checking, because the solution works for me, with one alteration: instead of passing @"en_us" into the rangeOfMisspelledWords... method I do the following:

UITextChecker* checker = [[UITextChecker alloc] init];
NSString* preferredLang = [[UITextChecker availableLanguages] objectAtIndex:0];
NSRange range;
range = [checker rangeOfMisspelledWordInString:currentWord
                                         range:NSMakeRange(0, [currentWord length]) 
                                    startingAt:0 
                                          wrap:NO
                                      language:preferredLang];

Followed by the same if-statement you use. The solution works, and will also work for users of other languages without change, should you decide to localize your app.

Perhaps for whatever reason the @"en_US" you're using is not the correct string to pass? It seems right though.


Probably you have forgotten ALLOC/INIT for UITextChecker

Works in this way:

- (IBAction)CheckWord:(id)sender
{
  UITextChecker *Checker = [[UITextChecker alloc] init];

  NSRange range = [Checker rangeOfMisspelledWordInString:[_Word.text lowercaseString] 
                                                    range:NSMakeRange(0, [_Word.text length]) 
                                               startingAt:0 wrap:NO 
                                                 language:@"it_IT"];

  if ( range.location == NSNotFound ) {
    _Esito.text = @"Word found";
  }
  else {
    _Esito.text = @"Word not found";
  }

  [Checker release];
}

For languages, use

NSLog(@"%@", [UITextChecker availableLanguages]);

hope this helps.

0

精彩评论

暂无评论...
验证码 换一张
取 消