In my OS X App, how can I change the NSTextField focus by pressing the Enter key instead of pressing the Tab key?
You may use NSText - (void)textDidEndEditing:(NSNotification *)aNotification delegate method, where you should use NSWindow’s makeFirstResponder: to change the current first responder. See the NSResponder class reference for details on this.
First set delegate of your firs textField to self. Then in same class:
- (void)textDidEndEditing:(NSNotification *)aNotification {
NSLog(#"delegate method");
[self.window makeFirstResponder:[[[aNotification object]window]nextResponder]];
}
I assume that you do this in AppDelegate class.
Related
#interface MyClass {
NSString *_myString;
}
#property (copy) *myString;
#end
#implementation MyClass
#synthesize myString = _myString;
- (void)awakeFromNib {
self.myString = #"";
}
In the nib, I have an NSTextField and an NSButton. The text field's Value binding is set to myClass.myString. I verified that the variable _myString is being updated correctly when text is typed into the text field.
The Enabled binding of the NSButton is set to myClass.myString.length. However, when I start up the program, the NSButton is enabled! If I go to the textfield and type something into it, the button stays enabled. Then if I erase the text from the textfield, the button becomes disabled.
But why isn't the button disabled to begin with, after the call in awakeFromNib ? Do I have to do some additional work to make the binding work in the opposite direction (myClass.myString --> NSTextField) ? I thought that declaring myString as a property would do the trick.
I'm not sure what is causing this but I would say the easiest way to fix it, since your text will start out empty, is in awakeFromNib do something like [myButton setEnabled:false];
I have two NSTextFields: textFieldUserID and textFieldPassword.
For textFieldPassword, I have a delegate as follows:
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
This delegate gets called when textFieldPassword has focus and I hit the enter key. This is exactly what I want.
My problem is that controlTextDidEndEditing also gets called when textFieldPassword has focus and I move the focus to textFieldUserID (via mouse or tab key). This is NOT what I want.
I tried using controlTextDidChange notification (which is getting called once per key press) but I was unable to figure out how to detect enter key ( [textFieldPassword stringValue] does not include the enter key). Can someone please help me figure this one out?
I also tried to detect if textFieldUserID was a firstResponder, but it did not work for me. Here is the code I tried out:
if ( [[[self window] firstResponder] isKindOfClass:[NSTextView class]] &&
[[self window] fieldEditor:NO forObject:nil] != nil ) {
NSTextField *field = [[[self window] firstResponder] delegate];
if (field == textFieldUserID) {
// do something based upon first-responder status
NSLog(#"is true");
}
}
I sure could use some help here!
If I understood you correctly, you could set an action for the password text field and tell the field to send its action only when the user types Return. Firstly, declare and implement an action in the class responsible for the behaviour when the user types Return on the password field. For example:
#interface SomeClass …
- (IBAction)returnOnPasswordField:(id)sender;
#end
#implementation SomeClass
- (IBAction)returnOnPasswordField:(id)sender {
// do something
}
#end
Making the text field send its action on Return only, and linking the action to a given IBAction and target, can be done either in Interface Builder or programatically.
In Interface Builder, use the Attributes Inspector, choose Action: Sent on Enter Only, and then link the text field action to an IBAction in the object that implements it, potentially the File’s Owner or the First Responder.
If you’d rather do it programatically, then:
// Make the text field send its action only when Return is pressed
[passwordTextFieldCell setSendsActionOnEndEditing:NO];
// The action selector according to the action defined in SomeClass
[passwordTextFieldCell setAction:#selector(returnOnPasswordField:)];
// someObject is the object that implements the action
[passwordTextFieldCell setTarget:someObject];
[passwordTextFieldCell setTarget:self];
[passwordTextFieldCell setAction:#selector(someAction:)];
- (void) someAction{
//handle
}
I have two NSTextFields: textFieldUserID and textFieldPassword.
For textFieldPassword, I have a delegate as follows:
- (void)controlTextDidEndEditing:(NSNotification *)aNotification
This delegate gets called when textFieldPassword has focus and I hit the enter key. This is exactly what I want.
My problem is that controlTextDidEndEditing also gets called when textFieldPassword has focus and I move the focus to textFieldUserID (via mouse or tab key). This is NOT what I want.
I tried using controlTextDidChange notification (which is getting called once per key press) but I was unable to figure out how to detect enter key ( [textFieldPassword stringValue] does not include the enter key). Can someone please help me figure this one out?
I also tried to detect if textFieldUserID was a firstResponder, but it did not work for me. Here is the code I tried out:
if ( [[[self window] firstResponder] isKindOfClass:[NSTextView class]] &&
[[self window] fieldEditor:NO forObject:nil] != nil ) {
NSTextField *field = [[[self window] firstResponder] delegate];
if (field == textFieldUserID) {
// do something based upon first-responder status
NSLog(#"is true");
}
}
I sure could use some help here!
If I understood you correctly, you could set an action for the password text field and tell the field to send its action only when the user types Return. Firstly, declare and implement an action in the class responsible for the behaviour when the user types Return on the password field. For example:
#interface SomeClass …
- (IBAction)returnOnPasswordField:(id)sender;
#end
#implementation SomeClass
- (IBAction)returnOnPasswordField:(id)sender {
// do something
}
#end
Making the text field send its action on Return only, and linking the action to a given IBAction and target, can be done either in Interface Builder or programatically.
In Interface Builder, use the Attributes Inspector, choose Action: Sent on Enter Only, and then link the text field action to an IBAction in the object that implements it, potentially the File’s Owner or the First Responder.
If you’d rather do it programatically, then:
// Make the text field send its action only when Return is pressed
[passwordTextFieldCell setSendsActionOnEndEditing:NO];
// The action selector according to the action defined in SomeClass
[passwordTextFieldCell setAction:#selector(returnOnPasswordField:)];
// someObject is the object that implements the action
[passwordTextFieldCell setTarget:someObject];
[passwordTextFieldCell setTarget:self];
[passwordTextFieldCell setAction:#selector(someAction:)];
- (void) someAction{
//handle
}
I have a modal sheet with an NSTextField control, an OK button and a Cancel push button. The OK button is bound to an action method called theSheetOK in my controller class. I also bound NSTextField control to an NSString member named foo in my controller (File's Owner) and I use key-value bindings to read the text value user entered (i.e. model-key path of text field in the bindings inspector is set to foo).
All works fine if the text is entered and user hits the OK button via keyboard. When I trace the value of foo with NSLog in theSheetOK handler I see the value I just typed in the text field.
However when I clicked the OK button with mouse, the value of foo is logged as empty, also as soon as I click the OK button, the text field control grabs the focus and the text I typed appears selected. Any ideas what went wrong?
#interface MyController : NSWindowController {
#private
NSString *foo;
}
#property (copy, readwrite)NSString* foo;
-(IBAction) theSheetOK:(id)sender;
-(IBAction) theSheetCancel:(id)sender;
#end
...
#import "MyController.h"
#implementation MyController
#synthesize foo;
-(IBAction) theSheetOK:(id)sender
{
NSLog(#"theSheetOK");
NSLog(#"foo= %#", foo);
...
NSWindow* theSheet = [self window];
[NSApp endSheet:theSheet returnCode: NSOKButton];
[theSheet orderOut:nil];
Sometimes you need to press enter to "confirm a change" to cocoa bindings. I'm not sure, but it's possible that when you hit enter both the change and button action are performed.
If that's the case, select your NSTextField and mark the option "Continuously Updates Value" so things get synced properly.
I´m newbie with cocoa. I have a button and a textField in my app. I want the button disabled when the textfield is empty and enabled when the user type something.
Any point to start? Any "magic" binding in Interface Builder?
Thanks
[EDITED]
I´ve tried to set the appDelegate as the NSTextfield´s delegate and added this method (myTextfield and myButton are IBOutlets):
- (void)textDidChange:(NSNotification *)aNotification
{
if ([[myTextField stringValue]length]>0) {
[myButton setEnabled: YES];
}
else {
[myButton setEnabled: NO];
}
}
But nothing happens...
I´ve tried to set the appDelegate as the NSTextfield´s delegate and added this method (myTextfield and myButton are IBOutlets):
- (void)textDidChange:(NSNotification *)aNotification
{
if ([[myTextField stringValue]length]>0) {
[myButton setEnabled: YES];
}
else {
[myButton setEnabled: NO];
}
}
That's the hard way, but it should work just fine. Either you haven't hooked up the text field's delegate outlet to this object, you haven't hooked up the myTextField outlet to the text field, or you haven't hooked up the myButton outlet to the button.
The other way would be to give the controller a property exposing the string value, bind the text field's value binding to this stringValue property, and bind the button's enabled binding to the controller's stringValue.length.
You could also give the controller two properties, one having a Boolean value, and set that one up as dependent upon the string property, and bind the button to that. That's a cleaner and possibly more robust solution, though it is more work.
Here's a solution using bindings.
Below I setup a NSTextField that is bound to the file owner's "text" property. "text" is a NSString. I was caught by "Continuously Updates Value". Thinking my solution didn't work but really it wasn't updating as the user typed, and only when the textfield lost focus.
And now setting up bindings on the button, simply set its enabled state to the length of the file owner's text property.
Annd, the working product.
If you use controlTextDidChange instead of textDidChange, you can get rid of the notification stuff and just rely on being the NSTextField's delegate.
Thanks Peter. What I missed (in my hard way version) is this piece of code in the awakeFromNib in the appDelegate:
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:#selector(textDidChange:) name:NSControlTextDidChangeNotification object:myTextField];
It works perfect. Now I´m trying the easy way, but I´m afraid I´m not still good enough with the bindings.
To bind the property
#property (retain) IBOutlet NSString *aStringValue;
with the textfield´s value, what I have to use in IB for "Bind to:", "Controller Key" and "Model Key Path"?