I have an NSComboBox. I've set an action selector. When the box gets hidden the selector fires, even if the user never touched it. Yes, I need to hide it.
IBOutlet NSComboBox *comboBox;
[comboBox setAction:#selector(onComboBoxSelection:)];
- (void)onComboBoxSelection:(id)sender
{
NSLog(#"Why does this fire twice");
//My code doesn't actually set hidden here, it's just for proof while debugging the issue.
[comboBox setHidden:YES];
}
Why would hiding an NSControl fire it's selector? What's the best way to fix it?
Update:
I've fixed it by wrapping the method. But I'd still like to understand why, or other ways to fix it.
- (void)onComboBoxSelection:(id)sender
{
if(![sender isHidden]{
NSLog(#"Now only fires once");
//My code doesn't actually set hidden here, it's just for proof while debugging the issue.
[comboBox setHidden:YES];
}
}
Set a breakpoint in onComboBoxSelection: and look at the backtrace when it's called the second time (type bt in the debugger to see the backtrace). That will explain what's going.
A combo box is both a text field and a popup, and it will fire actions for both. The text field action is fired when editing ends, either by hitting the Return key or when it resigns first responder (e.g., tabbing out to another field).
When you hide the combo box, the text field resigns first responder and fires its action.
What you probably want to do is check if combo box value has actually changed, and only then proceed with hiding the combo box, etc.
Another option is to use data bindings to observe changes to the combo box. Bind the combo box value to a property on your controller. Then implement the property setter in your controller.
try this [comboBox setHidden:1];
Related
I want to make a text field in which if I click out of it, or press enter, it makes it lose focus. As in the focus ring disappears. I've have seen situations like this, but I do not know where to place the code for it. Can anyone show me how to make the NSTextfield lose it's focus?
One method would be to implement the NSTextFieldDelegate, assign the delegate to your text field, and have it call a selector (a method in your code that changes makes the first responder = nil). The delegate will be called with a message when the text field is finished receiving input. Check out the API here for more information:
https://developer.apple.com/library/mac/documentation/cocoa/reference/NSTextFieldDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intf/NSTextFieldDelegate
For people out there as lazy as me, here is some code.
This is the cut down NSTextfieldDelegate method i used:
func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool {
DispatchQueue.main.async {
self.textField2.window?.makeFirstResponder(nil)
}
return true
}
https://developer.apple.com/documentation/appkit/nstextview/1807135-resignfirstresponder?language=objc
resignFirstResponder Docu says the following:
Use the NSWindow method makeFirstResponder:, not this method, to make
a text view the first responder. Never invoke this method directly.
// don't use this as the name may suggest (at least it did for me)
self.textField2.resignFirstResponder()
I have a set of UIButtons (defined in a xib) who have labels that need to be updated periodically. In the ViewDidLoad method of the view controller of those buttons' superview, I have an update method that does, for each button:
button.titleLabel.text = #"Relevant Text";
[button setNeedsDisplay];
and when you tap a button, another method runs which pops up a UIAlertView, which in turn calls back a method on the view controller which does much the same thing as the initial text setting method:
button.titleLabel.text = #"New Text";
[button setNeedsDisplay];
however, this code simply isn't working, the button label's text doesn't get updated in either method, it remains a blank white button. In the xib I don't define any text on the buttons - there's no point, the button text doesn't make sense unless it's set at runtime. Anyway, on a lark, I decided to set the text of one of the buttons to "test test test".
Now, when I tap that particular button, it pops up the UIAlertView but in the background changes the text of the button to "test test test test". And this time, the UIAlertView callback does what I expect it to and sets the text for only that button. When I hit it again, the text goes back to "test test test test" until I dismiss the UIAlertView, which again will run the callback method and set the button text to whatever the method should.
I have no idea what's going on here, or why setting the text initially in the xib has any relation to whether or not I can set that text later programatically. Obviously this isn't the behavior I want, I want to know how to for sure set the text on the buttons.
Edit: SVD's advice about setTitle:ForState: solved my problem, thanks. I'm still curious though as to why the title label set in the .xib shows up, but only when I have a UIAlertView pop up.
You may need to use [setTitle: forState:] to set the button title for normal and highlighted (or selected) state.
(And do make sure the button is connected to the outlet, as jtbandes points out).
I have a set of UIButtons (defined in a xib) who have labels that need to be updated periodically. In the ViewDidLoad method of the view controller of those buttons' superview, I have an update method that does, for each button:
button.titleLabel.text = #"Relevant Text";
[button setNeedsDisplay];
and when you tap a button, another method runs which pops up a UIAlertView, which in turn calls back a method on the view controller which does much the same thing as the initial text setting method:
button.titleLabel.text = #"New Text";
[button setNeedsDisplay];
however, this code simply isn't working, the button label's text doesn't get updated in either method, it remains a blank white button. In the xib I don't define any text on the buttons - there's no point, the button text doesn't make sense unless it's set at runtime. Anyway, on a lark, I decided to set the text of one of the buttons to "test test test".
Now, when I tap that particular button, it pops up the UIAlertView but in the background changes the text of the button to "test test test test". And this time, the UIAlertView callback does what I expect it to and sets the text for only that button. When I hit it again, the text goes back to "test test test test" until I dismiss the UIAlertView, which again will run the callback method and set the button text to whatever the method should.
I have no idea what's going on here, or why setting the text initially in the xib has any relation to whether or not I can set that text later programatically. Obviously this isn't the behavior I want, I want to know how to for sure set the text on the buttons.
Edit: SVD's advice about setTitle:ForState: solved my problem, thanks. I'm still curious though as to why the title label set in the .xib shows up, but only when I have a UIAlertView pop up.
You may need to use [setTitle: forState:] to set the button title for normal and highlighted (or selected) state.
(And do make sure the button is connected to the outlet, as jtbandes points out).
There sure are a lot of UIButton questions here, and I was hoping to find the answer to this, but nothing quite like this particular issue.
I have a few buttons, and I can call button.highlighted = YES; for any button when the program runs and it shows up highlighted.
I thought I could then use this same technique to set a button's highlight state to YES after it pressed, and then set it to NO after another button is pressed. This way, the current selection remains highlighted.
For example:
-(IBAction) buttonPressed:(UIButton *)button
{
if (button.tag==1)
{
self.button1.highlighted=YES;
self.button2.highlighted=NO;
// do other program stuff here
}
if (button.tag==2)
{
self.button2.highlighted=YES;
self.button1.highlighted=NO;
// do other program stuff here
}
}
Even though the highlights work fine if I place the highlighted = YES; code inside viewDidLoad. But the above code does not work. The highlight doesn't stick. The buttons works, and does the other stuff it needs to do, but the highlights fail to stick.
I would think this should be pretty basic. Is iOS somehow automatically setting all button highlights to NO on its own after any button operation?
May be you should use other means to present the highlight status, because of the statement from UIControl's documentation:
By default, a control is not
highlighted. UIControl automatically
sets and clears this state
automatically when a touch enters and
exits during tracking and when there
is a touch up.
You might try using the 'selected' property instead of the 'highlighted' property.
I have a view with a nssearchfield a nstableview and a nsmatrix with three radiobuttons. Using delegates i change the selected radiobutton when the searchfield is the firstresponder and the user press tab, that works perfectly but what i want is that the searchfield don't loose the firstresponder when the user press tab
You can sub class NSSearchField and add this function
- (BOOL)resignFirstResponder {
return NO;
}
It will refuse to relinquish first responder status.
Another way is catch the windowDidUpdate notification. These are sent whenever anything changes, including change of focus, so you can check for the firstResponder and make it become first responder again.
[searchField becomeFirstResponder];