views:

261

answers:

2

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];
+1  A: 

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

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

each time?

Kenny
I am referring to NSTextField not UITextField. This is a Mac OS X desktop question.
Luke
I was hoping there was something better than using textDidChange. I notice that the default menu bar is hooked up to toggleAutomaticSpellingCorrection: on the Edit > Spelling and Grammar > Check Spelling While Typing option. This menu option works with the NSTextField once the application is running. I would like to know how to enable that official option thought the Obj-C code.
Luke
You might like to remove the wrong iPhone suggestion from your answer so it doesn't show up in Google.
Luke
+2  A: 

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];
pheelicks
That doesn't seem to indicate how I can enable "as-you-type" spell checking like I can from the Edit menu. I am I missing something here?
Luke
See updated answer
pheelicks
Well the NSTextView doesn't support the Focus Ring property which I didn't want to re-invent for this situation. I don't really understand why I can't programmatically turn the Spelling options that I can access in the Edit > Spelling and Grammar menu when using the NSTextField. Shouldn't there be some way to turn that option on through Obj-C code?
Luke
Also, the NSTextField can easily handle an action for the return event.
Luke
How about editing MainMenu.xib to set the option directly? See edit
pheelicks
Yes, I tried that just before and when the application loads the menu option will be disabled regardless of what it was setup as in IB. Shouldn't I be able to run that menu item using code? I am quite new to Objective-C so I don't know where to start with that.
Luke
Try what I have above. I'm not 100% on the 2nd line (accessing the actual item) but I can't test it as my mac is broken - but something along these should work for you.
pheelicks
I tried the code after I modified it to traverse the menus. All objects were set but the setEnabled:YES didn't work. See my update #1 in the original question.
Luke
See update. Seems setEnabled only sets the item, but doesn't actually perform the action.
pheelicks
Thanks, I think we are getting close. [[autoSpellingMenuItem target] performSelector:[autoSpellingMenuItem action]]; doesn't run the action though. Also the setEnabled doesn't actually set the checkbox on the MenuItem. Either way the MenuItem has a Send Action of continuousSpellChecking: connected to First Responder. Is there anyway to run this action without using traversing the menus?
Luke
Also, check my update #1 again in the original question. The target seems to output null, however the MenuItem object is there.
Luke
Find out what your first responder (http://stackoverflow.com/questions/1823317/how-do-i-legally-get-the-current-first-responder-on-the-screen-on-an-iphone) and then send it a message: [firstResponder continuousSpellChecking:YES]; ?
pheelicks
Some NSLogging showed me that after setting the NSTextField to firstResponder the firstResponder actually contains a NSTextView, you can then enable the spelling. See the solution in the original question. I assume the NSTextField contains a NSTextView in the subviews which takes the responder, really this should be exposed in the NSTextField class.
Luke
Thanks for all your help! Add the solution to your answer as well and I will mark you as the answer.
Luke