Is it possible to have an if statement that looks if a button has been pressed?
if(condition) {
//Do something
}
What has to go as the condition?
A UIButton will call a method, to which it is wired up in Interface Builder or set to in code.
If you need to know in certain parts of your program, if a button was pressed, you can do something like this:
-(IBAction)buttonTapped:(UIButton *) sender
{
self.buttonPressed = YES; //bool instance variable with property
}
-(void)someOtherMethod
{
if(self.buttonPressed){
//do what you want to do, if button pressed
}
}
But I think, coupling the UI and logic so tight on a semantic level, is no good idea.
Related
I have an NSWindow with a main "OK" button. This button has as "key equivalent" property in interface builder, the key ENTER i.e ↵.
It works good, but now I have a new NSComboBox, which is supposed to invoke a method when the user selects a list item, or he preses Enter / ↵.
However, when I press Enter, the main Button receive the notification and the window close. How to prevent this?
This is the normal behavior what you are getting, but you can hack a bit, by removing and adding the key-equivalent.
Add following delegates of NSComboBox:
- (void)comboBoxWillPopUp:(NSNotification *)notification;{
[self.closeButton setKeyEquivalent:#""];
}
- (void)comboBoxWillDismiss:(NSNotification *)notification;{
[self.closeButton setKeyEquivalent:#"\r"];
}
One way you can workaround for prevent enter notification is like that below:-
//Connect this action method to your combobbox and inside that set one BOOL flag to yes
- (IBAction)comBoxItm:(id)sender
{
self.isEnterCalled=YES;
}
//Now check this flag to your some method where close window is called
-(void)someMethod
{
//Check the flag value if it is yes then just ignore it
if (!self.isEnterCalled)
{
//Close window logic
}
self.isEnterCalled=NO;
}
Ran into the same problem. Had "hot key" which I'd like to switch off while editing some text fields. I found solution for myself. There's no need in override lots of NSTextField base methods.
Firstly, I removed all the "key equivalents". I used to detect Enter key down with the + (void)addLocalMonitorForEventsMatchingMask:(NSEventMask)mask handler:(NSEvent *(^)(NSEvent *))block class method of NSEvent. You pass block as a parameter, where you can check for some conditions. The first parameter is the event mask. For your task it would be NSKeyDownMask, look for other masks at the NSEvent Reference Page
The parameter block will perform each time the user pushes the button. You should check if it is right button pushed, and - generally - if the current window first responder isn't some editable control. For that purposes we need NSWindow category class just not to implement this code each time we deal with NSKeyDownMasked local monitors.
NSWindow+Responders class listing:
#interface NSWindow (Responders)
- (BOOL)isEditableFirstResponder;
#end
#implementation NSWindow (Responders)
- (BOOL)isEditableFirstResponder
{
if (!self.firstResponder)
return NO; // no first responder at all
if ([self.firstResponder isKindOfClass:[NSTextField class]]) // NSComboBox is NSTextField subclass
{
NSTextField *field=(NSTextField *)self.firstResponder;
return field.isEditable;
}
if ([self.firstResponder isKindOfClass:[NSButton class]]) // yep, buttons may be responders
return YES;
return NO; // the first responder is not NSTextField or NSButton subclass - not editable
}
#end
Don't know if there's another way to check if we are now editing some text field or combo box. So, there's at least the part you add the local monitor somewhere in your class (NSWindow, NSView, some controller etc.).
- (void)someMethod
{
id monitor=[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:(NSEvent *)^(NSEvent *theEvent){
if (theEvent.keyCode==/*Enter key code*/ && ![self.window.isEditableFirstResponder]) // you should check the key modifiers too
{
// your code here
}
return theEvent; // you may return the event to pass the key to the receiver
}];
}
Local monitors is safe remedy about the Apple rules. It works only inside your application. For global key down events you may use addGlobalMonitor but Apple may reject your app from the AppStore.
And don't forget to remove the monitor when there's no need in it.
- (void)viewControllerShutdownMethod
{
[NSEvent removeMonitor:monitor];
}
Good luck.
I have search and can't find any information so I would like some help here. I am new to Xcode and objective c. I have 10 NSButtons set in Interface Builder to be Push On Push Off type. I am trying to figure out how when one of the buttons is clicked and highlighted, how do I unhightlight the other nine. I am use to Java, in java you can just make an if statement to turn off the highlight of the buttons not clicked. In IB I don't see how to send a message to the other buttons because I don't know their "names" or addresses. Can you please help me figure this out, explain it or send me to a link or video. Thank you.
This is what I've used in the past.
Create an NSArray with all your buttons in it, something like:
NSArray* buttons = #[button1, button2, button3, button4];
Then create a method like this.
- (void) toggleButtons: (id) sender {
for (Button *item in buttons) {
if (item == sender) {
item.selected = !item.selected;
} else {
item.button.selected = NO;
}
}
}
Now call it from each of your button handlers:
- (IBAction) handleButton1:(id) sender {
[self toggleButtons:sender];
<...rest of your code...>
}
How can I write a function that will take either a UIView or a UIButton as a parameter.
For example, let's say I wanted to round the corners the View/Button:
[self roundCorners:x]
How could I make that accept both a UIButton object or a UIView object as x?
My first thoughts were use id or NSObject, but I don't think that is correct:
-(void)roundCorners:(id)objectToRound;
UIButton is a subclass of UIView, so your method will take either one if you declare it this way:
- (void)roundCorners:(UIView *)objectToRound;
Short answer:
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *) view;
// do something funky with button
} else {
// do something funky with view
}
Detailed answer:
First of all, it is usually best to have a specific method to handle each class of object. This is so you can have the compiler resolve potentially passing the wrong class to a method. There are however times when this is not appropriate or possible.
UIView and UIButton are both ultimately a descendant of NSObject.
NSObject has a method isKindOfClass: which you can use to determine what you are dealing with. I have taken it a step further by defining a few helper macros that simplify these sorts of tasks, which are sometimes quite laborious.
If you have a look at my answer to this question... you will see source code for, and an example of using these macros. I often use one of these macros (asClass), which combines a isKindOfClass: test linked to a type cast to the class being tested for.
You can code such a thing long hand, however I find it creates more readable code to use the asClass macro. Put simply asClass(myView,UIButton) will either resolve to nil or to a type cast reference to myView as a UIButton - if it is not a UIButton, it will be resolved to nil.
I have modified a snippet from that post to suit your question:
- (void)myMethod:(UIView*)view{
UIButton *button = asClass(view, UIButton);
if (button) {
// do something funky with button
} else {
// do something funky with view
}
}
To code this long hand, (without macros) it would look approximately like this:
- (void)myMethod:(UIView*)view{
if ([view isKindOfClass:[UIButton class]]) {
UIButton *button = (UIButton *) view;
// do something funky with button
} else {
// do something funky with view
}
}
As you can see, it's not too much extra code to do it long hand, and if you are not comfortable using macros for things like this (some people aren't) then you may choose to stick with the second example.
If you are comfortable with macros, and can see the merits of the approach I have taken, consider this third way of doing it:
- (void)myMethod:(UIView*)view{
UIButton *button;
if ( (button = asClass(view, UIButton)) ) {
// do something funky with button
} else {
// do something funky with view
}
}
The way you do it should work just fine, id will accept almost anything.
I'm rather new to programming in Cocoa, but I've been working on learning the language quite diligently up until I hit this snag that I can't seem to circumvent/hack my way around, (not that I'd want to. I'd prefer to do it right!)
Where I stand, In IB I have a toolbar that has a button and what I'm trying to do is mimic the maps app. I want to be able to press the button and then have my location pop up, while keeping the button selected, then when it's pressed again, deselect it and thus remove the blue blip location from the map.
ideally, I would like to use the following code, but the if statement doesn't seem to want to work on the simulator (which I presume wouldn't change if I tried on the iPhone.)
-(IBAction) showLocation: (id) sender
{
if([sender isSelected]) // this doesn't work!!
{
[sender setSelected:NO];
mapView.showsUserLocation = FALSE;
}
else
{
[sender setSelected:YES];
mapView.showsUserLocation = TRUE;
}
}
obviously if I get rid of the if statement, I know that I can show the location and set the selected as I liked, but I can't seem to "get" the selected property from the button... what's the right way of doing this?
try
- (void)methodName:(UIButton *)sender
{
if (sender.selected == YES) ...
how should i take NSButton text value , e.g if i use 2 buttons with text Click and Cancel, i want to check which button is clicked and then show a message with NSRunAlertPanel(...) which button i have clicked..what code should i write for it when the button is clicked.
In you action method you get an argument, usually named 'sender', which is the button. So you could do something like:
- (IBAction)buttonClicked:(id)sender
{
if ([[sender title] isEqualToString:#"Click"]) {
NSLog(#"Click clicked.");
} else if ([[sender title] isEqualToString:#"Cancel"]) {
NSLog(#"Cancel clicked.");
}
}
It's better not to use the title for checking the button, since the title could change in different localizations. You could specify the tag instead, which is simply an int and which can be used to identify different senders.
The way this is typically implemented is that each button would call a different action, thus there would be no need to check the text of the button. See The Target-Action Mechanism.
In general it is almost always a bad idea to use the user visible text to control program logic because that makes localization harder.
You might also want to describe your situation further. Are you using Interface Builder to create your interface? Are these buttons in a modal dialog or a document window?
You could give the button a name in the class info tab of the inspector window in Interface Builder, then declare it as an IBOutlet in your app delegate.
AppDelegate.h:
IBOutlet NSButton *ClickButton;
IBOutlet NSButton *CancelButton;
Then hook up the outlet in Interface Builder, and just check to see which button is the sender in your method:
- (IBAction)buttonClicked:(id)sender
{
if (sender == ClickButton) {
NSLog(#"Click clicked.");
}
else {
NSLog(#"Cancel clicked.");
}
}