9

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];
Luke
  • 6,195
  • 11
  • 57
  • 85
  • 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 Jun 13 '17 at 07:28

2 Answers2

4

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
  • 7,461
  • 2
  • 45
  • 50
  • 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 May 13 '10 at 08:35
  • 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 May 13 '10 at 10:59
  • Also, the NSTextField can easily handle an action for the return event. – Luke May 13 '10 at 12:29
  • How about editing MainMenu.xib to set the option directly? See edit – pheelicks May 13 '10 at 12:52
  • 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 May 13 '10 at 13:08
  • 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 May 13 '10 at 13:33
  • 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 May 13 '10 at 14:28
  • See update. Seems setEnabled only sets the item, but doesn't actually perform the action. – pheelicks May 13 '10 at 14:40
  • 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 May 13 '10 at 14:50
  • Also, check my update #1 again in the original question. The target seems to output null, however the MenuItem object is there. – Luke May 13 '10 at 14:55
  • 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 May 13 '10 at 15:09
  • 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 May 13 '10 at 15:24
  • Thanks for all your help! Add the solution to your answer as well and I will mark you as the answer. – Luke May 13 '10 at 15:24
1

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

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

each time?

gnasher
  • 1,513
  • 12
  • 17
  • I am referring to NSTextField not UITextField. This is a Mac OS X desktop question. – Luke May 13 '10 at 08:28
  • 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 May 13 '10 at 08:50
  • You might like to remove the wrong iPhone suggestion from your answer so it doesn't show up in Google. – Luke May 13 '10 at 13:12