9
votes

I have an NSTextField that I would like to enable "as-you-type" spell checking. When I load my application I can do this from the Menu Bar > Edit > Spelling and Grammar > Check Spelling While Typing.

I would like this option to be enabled by default. Within IB I can enable this for a NSTextView but I would like to use NSTextField for this part of the UI.

Thank you.

Update: Does anyone know if it is possible to programatically run the Menu Bar > Edit > Spelling and Grammar > Check Spelling While Typing option on the NSTextField from Objective-C code? It seems that the NSTextField supports the "Check Spelling While Typing" option, just there is no way to enable the option from Obj-C.

Edit #1

I tried the following to manually enable the menu and it didn't work:

// Focus TextField
[textField becomeFirstResponder];

// Enable Spell Checking
NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
NSMenu *editMenu = [[mainMenu itemWithTitle:@"Edit"] submenu];
NSMenu *spellingMenu = [[editMenu itemWithTitle:@"Spelling and Grammar"] submenu];
NSMenuItem *autoSpellingMenuItem = [spellingMenu itemWithTitle:@"Check Spelling While Typing"];
[autoSpellingMenuItem setEnabled:YES];

NSLog(@"Menu: %@", [autoSpellingMenuItem description]);
NSLog(@"Target: %@", [[autoSpellingMenuItem target] description]);

// Actually perform menu action
[[autoSpellingMenuItem target] performSelector:[autoSpellingMenuItem action]];

Is it not possible to directly call the menu item action rather than using the setEnabled:YES ?

The above outputs the following, not sure why the target is null

App[3895:a0f] Menu: <NSMenuItem: 0x100135180 Check Spelling While Typing>
Current language:  auto; currently objective-c
App[3895:a0f] Target: (null)

SOLUTION

Below is the solution for this issue if anyone else needs to know. Some NSLogging showed me that after setting the NSTextField to firstResponder the firstResponder actually contains a NSTextView, you can then enable the spelling. I assume the NSTextField contains a NSTextView in the subviews which takes the responder, really this should be exposed in the NSTextField class.

// Focus TextField
[textField becomeFirstResponder];

// Enable Continous Spelling
NSTextView *textView = (NSTextView *)[self.window firstResponder];
[textView setContinuousSpellCheckingEnabled:YES];
2
The NSTextView that appears is called the field editor. If this firstResponder casting is too fragile, you can override -windowWillReturnFieldEditor:forObject: in the NSWindowController and change settings there.ctietze

2 Answers

4
votes

You're in luck, Apple provides a spellchecker class: NSSpellChecker:

http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/SpellCheck/Concepts/SpellChecker.html

Using this you can check the the spelling every time the user updates the text by using the textdidChange delegate method.

Also you say you want to use NSTextField rather than NSTextView. Why not just use an editable NSTextView where you can set the toggleAutomaticSpellingCorrection property?

EDIT:

To change the value of the menu item programatically do something along the lines of:

// Enable Spell Checking
NSMenu *mainMenu = [[NSApplication sharedApplication] mainMenu];
NSMenu *editMenu = [[mainMenu itemWithTitle:@"Edit"] submenu];
NSMenu *spellingMenu = [[editMenu itemWithTitle:@"Spelling and Grammar"] submenu];
NSMenuItem *autoSpellingMenuItem = [spellingMenu itemWithTitle:@"Check Spelling While Typing"];
[autoSpellingMenuItem setEnabled:YES];

// Actually perform menu action
[[autoSpellingMenuItem target] performSelector:[autoSpellingMenuItem action]];

EDIT:

It seems that the above method does not actually fire off the method as it is supposed to and the target is NULL (because the first responder has not been set?). It is however possible to send the message directly, like so:

// Focus TextField
[textField becomeFirstResponder];

// Enable Continous Spelling
NSTextView *textView = (NSTextView *)[self.window firstResponder];
[textView setContinuousSpellCheckingEnabled:YES];
1
votes

Have you tried tapping into the NSTextField delegate method textDidChange: and calling:

range = [[NSSpellChecker sharedSpellChecker] checkSpellingOfString:aString startingAt:0];

each time?