I'm new to Objective-C, and I'm trying to create an app with two buttons that toggle off and on in tandem. I've handled the button states (images for on and off) in Interace Bulder, but I'm having trouble figuring out exactly how to write the logic in Xcode.
Here are the conditions I need to fulfill:
-When neither button is on, either button may be turned on.
-When button1 is on, and button2 is clicked, button1 turns off, and button 2 turns on.
-When button2 is on, and button1 is clicked, button2 turns off, and button 1 turns on.
-When button1 is on and button1 is clicked, nothing happens.
-When button2 is on and button2 is clicked, nothing happens.
I've been using BOOL to try and work out the logic, but it's just not happening for me. Does anyone have an idea of how to do this?
The buttons were added programatiaclly, so the simple code looks like this in the .h file:
in .h:
#import <UIKit/UIKit.h>
#interface Profile_Settings_PageViewController : UIViewController {
IBOutlet UIButton *Button1;
IBOutlet UIButton *Button2;
BOOL ButtonSelected;
}
#property (nonatomic, retain) UIButton *Button1;
#property (nonatomic, retain) UIButton *Buton2;
-(IBAction) ButtonTouched:(id)sender;
#end
then the .m file:
#import "Profile_Settings_PageViewController.h"
#implementation Profile_Settings_PageViewController
#synthesize Button1;
#synthesize Button2;
-(IBAction) ButtonTouched:(id)sender
{
if (ButtonSelected == 0)
{
[Button1 setSelected: NO];
[Button2 setSelected: NO];
ButtonSelected = 1;
}
else if (ButtonSelected == 1)
{
[Button1 setSelected: YES];
[Button2 setSelected: YES];
ButtonSelected = 0;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
ButtonSelected == 0;
}
- (void)dealloc {
[Button1 release];
[Button2 release];
[super dealloc];
}
#end
The issue I'm having is where the if statement begins. I'm not sure how to point to the specific buttons for the logic. I know what's there now is not correct both because it applies to both buttons, and because the logic is wrong, which creates problems when writing the conditional statements. I'm not sure how to fix it though...
If your image states are for NORMAL and SELECTED, create two buttons with outlets, tag them 1 & 2 respectively, and in your button action method:
Start with button 1 selected, button 2 normal.
- (IBAction)buttonAction:(UIButton*)sender
{
if (sender.selected)
return;
if (sender.tag == 1)
{
button1.selected = !button1.selected;
button2.selected = !button1.selected;
}
else if (sender.tag == 2)
{
button2.selected = !button2.selected;
button1.selected = !button2.selected;
}
}
int selectedIndex = -1;
if( selectedIndex != 1 && b1 clicked ) { selectedIndex = 1; do stuff }
if( selectedIndex != 2 && b2 clicked ) { selectedIndex = 2; do stuff }
i.e.:
have a "which button is selected"
state
have a "nothing is selected"
state
check each click against that
selected/not-selected, and update it
when things happen
Assuming you have figured out how to wire up your buttons in IB so that they call a method in your viewController when switched. Define two outlets in your view controller (one for each button) and an action to be called when the value of a switch changes:
#interface ToggleViewController : UIViewController {
UISwitch *button1;
UISwitch *button2;
}
#property (nonatomic, retain) IBOutlet UISwitch *button1;
#property (nonatomic, retain) IBOutlet UISwitch *button2;
- (IBAction)switchAction:(id)sender;
#end
Ensure you connect the outlets and also connect the Value Changed event to the switchAction for both buttons. The switch action method can then be something along these lines:
- (IBAction)switchAction:(id)sender {
if ([sender isOn]) {
if ([sender isEqual:button1])
{
[button2 setOn:NO animated:YES];
} else {
[button1 setOn:NO animated:YES];
}
}
}
It's pretty simple: when either button is touched, you want to turn the other off. So in the UIControlEventTouchUpInside handler for button1, set button2 off. And in the UIControlEventTouchUpInside handler for button2, set button1 off.
For swift3 this is working
#IBAction func mealsButtonAction(_ sender: UIButton)
{
if sender .isEqual(beforeMealsButton)
{
beforeMealsButton.isSelected = true
beforeMealsButton .setImage(UIImage.init(named: "before_lunch_hover"), for: .normal)
afterMealsButton .setImage(UIImage.init(named: "after_lunch_normal"), for: .normal)
boolDict["bm"] = true
boolDict["am"] = false
}
else
{
afterMealsButton.isSelected = true
beforeMealsButton .setImage(UIImage.init(named: "before_lunch_normal"), for: .normal)
afterMealsButton .setImage(UIImage.init(named: "after_lunch_hover"), for: .normal)
boolDict["bm"] = false
boolDict["am"] = true
}
}
Thank you #Rog.
Related
In my ViewController I have added A UISegmentedControl to preform different task for a different selection of the Segmented Control. Its a cards matching game.
And everything seems to work just fine, except that the Segmented Control is not reacting to the selection.., I created a switch to do something in case of "twoCardGame" and in case of "threeCardGame".
From what I understand it would be good to define those variables with enum, which I did in the top part of the controller, but it seems like i'm missing something in it..
Sorry if its not so directed, but my controller is pretty short and simple, would appreciate if you can tell me what am I doing wrong in term of the UISegmentedControl.
Here it is:
#import "CardGameViewController.h"
#import "PlayingCardsDeck.h"
#import "CardMatchingGame.h"
enum CardGame {
twoCardGame,
threeCardGame
};
#interface CardGameViewController ()
#property (weak, nonatomic) IBOutlet UILabel *notificationLabel;
#property (weak, nonatomic) IBOutlet UILabel *scoreCounter;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
#property (strong, nonatomic) CardMatchingGame *game;
#property (weak, nonatomic) IBOutlet UISegmentedControl *numberOfCardsToPlayWith;
#end
#implementation CardGameViewController
//creating the getter method that creates a new card game.
- (CardMatchingGame *)game {
if (!_game) {
_game = [[CardMatchingGame alloc] initWithCardCount:self.cardButtons.count
usingDeck:[[PlayingCardsDeck alloc] init]];
_game.numberOfCardsToPlayWith = [self selectNumberOfCardsToPlayWith];
}
return _game;
}
//creating a setter for the IBOutletCollection cardButtons
-(void)setCardButtons:(NSArray *)cardButtons {
_cardButtons = cardButtons;
[self updateUI];
}
- (void)updateUI {
for (UIButton *cardButton in self.cardButtons) {
Card *card = [self.game cardAtIndex:[self.cardButtons indexOfObject:cardButton]];
[cardButton setTitle:card.contents forState:UIControlStateSelected];
[cardButton setTitle:card.contents
forState:UIControlStateSelected|UIControlStateDisabled];
cardButton.selected = card.isFaceUp;
cardButton.enabled = !card.isUnplayable;
cardButton.alpha = card.isUnplayable ? 0.3 : 1.0;
}
self.scoreCounter.text = [NSString stringWithFormat:#"Score: %d", self.game.score];
}
//Here I created a method to flipCards when the card is selected, and give the user a random card from the deck each time he flips the card. After each flip i'm incrementing the flipCount setter by one.
- (IBAction)flipCard:(UIButton *)sender {
[self.game flipCardAtIndex:[self.cardButtons indexOfObject:sender]];;
[self updateUI];
}
//sending an alert if the user clicked on new game button
- (IBAction)newGame:(UIButton *)sender {
UIAlertView* mes=[[UIAlertView alloc] initWithTitle:#"Think about it for a sec..?" message:#"This will start a new game" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes", nil];
[mes show];
}
- (NSUInteger)selectNumberOfCardsToPlayWith {
switch (self.numberOfCardsToPlayWith.selectedSegmentIndex) {
case twoCardGame:
return 2;
case threeCardGame:
return 3;
default:
return 2;
}
[self updateUI];
}
//preforming an action according to the user choice for the alert yes/no to start a new game
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex != [alertView cancelButtonIndex]) {
self.game = nil;
for (UIButton *button in self.cardButtons) {
Card *card = [self.game cardAtIndex:[self.cardButtons indexOfObject:button]];
card.isUnplayable = NO;
card.isFaceUp = NO;
button.alpha = 1;
}
self.notificationLabel.text = nil;
[self updateUI];
}
}
#end
Well, I don't see any addTarget: calls to segmented control. So you probably set them in Interface Builder. Check IB connections. If everything in IB seems ok -- try to addTarget: programmatically.
I think you'd be better off creating a selector and adding it to the segmented control target like so:
[segmentedControl addTarget:self
action:#selector(selectNumberOfCardsToPlayWith:)
forControlEvents:UIControlEventValueChanged];
- (NSUInteger)selectNumberOfCardsToPlayWith:(UISegmentedControl *)control {
switch (control.selectedSegmentIndex) {
case twoCardGame:
return 2;
case threeCardGame:
return 3;
default:
return 2;
}
[self updateUI];
}
This should work fine. Using similar code myself currently.
I am very new to iPhone development. I am trying to disable an already existing button but I cant actually obtain a pointer to a specific element in the view. For instance, I have the following in the viewController header
- (IBAction)one:(id)sender;
and the implementation is
- (IBAction)one:(id)sender {
}
which are just event handlers. However, I need disable the button when view opens and I am a little bit lost on how to obtain references to elements outside of the event handler.
So in other words, my thought is to have something like:
UIButton* myButton = //something
where the something is where I am lost on what to do. Any ideas? I greatly appreciate any help I get on here!
You need to create a property for your button in the interface:
#property(nonatomic, retain) IBOutlet UIButton * button;
And add this to implementation:
#synthesize button;
Then connect the button to it in interface builder. After this you can disable the button by:
button.enabled = NO;
Hope I could help!
Just give tag to your button and access your button with tag value.
UIButton *btn = (UIButton*)[self.view viewWithTag:1];
[btn setHidden:YES];
In your .h File
#import <UIKit/UIKit.h>
#interface RpViewController : UIViewController
#property (retain , nonatomic)IBOutlet UIButton *Btn1;
#end
In your .m file , in implementation write this :
#synthesize Btn1;
Now on interface , click on button.
In button's properties - > Drawings - check Hidden checkbox.
Wherever you want to show that button , just write.
[Btn1 setHidden:FALSE];
#property (strong, nonatomic) UIButton *button;
#synthesize button;
// In View Did Load...
self.button = [UIButton buttonWithType:UIButtonTypeCustom]; // button can be of any type.
[self.button setTag:1];
// if you have more buttons initialize it and set its tag. you can get to know which button was pressed using tags.
[button addTarget:self action:#selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside];
-(void) buttonEvent:(UIButton *) sender
{
NSLog(#"%d",sender.tag);
if(sender.tag == 1)
{
[self.button setEnabled:NO]; // This makes your button disabled, i.e you can see the button but you cannot click on it.
[self.button setHidden:YES]; // This makes your button hidden.
}
}
if you have more doubts ping me back.
I have an IBOutletCollection of UIButtons:
#property (nonatomic, retain) IBOutletCollection(UIButton) NSMutableArray *Buttons;
with an ibaction i would to change the highlighted state permanently after the touch down event.
This Problem is very similar to this:
IBOutletCollection of UIButtons - changing selected state of buttons
... but with the for-loop the buttons doesnt change.
i also tried the perfomselector method from here: Keep iPhone UIButton Highlighted
but it doesnt work.
now my code:
-(IBAction)toggleButtons:(id)sender
{
NSUInteger Index = [button tag];
[[Buttons objectAtIndex:Index] setHighlighted:YES];
}
if i change line four to this:
[[Buttons objectAtIndex:3] setHighlighted:YES];
it works for the fourth element in my collection... But not with the index variable....
regards, phil
Update
SelectionViewController.h
#import <UIKit/UIKit.h>
#interface SelectionViewController : UIViewController
#property (nonatomic, retain) IBOutletCollection(UIButton) NSMutableArray *Buttons;
- (IBAction)toggleButtons:(id)sender;
#end
SelectionViewController.m
#import "SelectionViewController.h"
#interface SelectionViewController ()
#end
#implementation SelectionViewController
#synthesize Buttons;
-(IBAction)toggleButtons:(id)sender
{
UIButton *button = sender;
NSUInteger Index = [button tag];
[self performSelector:#selector(doHighlight:) withObject:sender afterDelay:0];
[[Buttons objectAtIndex:Index] setHighlighted:YES];
}
- (void)doHighlight:(UIButton *)b {
[b setHighlighted:YES];
}
Okey Update 2:
Now i had declared my Buttons as normal IBOutlet and this is not working:
-(IBAction)toggleButtons:(id)sender
{
UIButton *button = sender;
[button setHighlighted:YES];
}
But if change it to this:
-(IBAction)toggleButtons:(id)sender
{
[myOutletButton setHighlighted:YES]; //Normal Outlet
}
it works....
But why is not possible with the sender?
regards!
Update 3
This works also:
for(id button in self.view.subviews)
{
[button setHighlighted:YES];
}
Ok if change the delay time in the selector to 1, the state will be highlighted. I am using "touch down" event... i think after i touched up the button gets its old state. Which event is the right?
Given that your example works with a specific integer, the problem is probably that the tag property is not set properly for each of your buttons. If the buttons are created in interface builder, each of them will have a default tag value of 0. To check this, click on the button and then, in the Attributes Inspector, scroll down to View and see what value is entered in the tag field
For the iPhone, I havent been able to find anything like a radio button that triggers the other buttons in a group. So what would everyone suggest using? UISwitch I guess and do something to trigger the others in the group when an other is selected?
If I had several UISwitch objects how would I trigger the others to be the opposite of what I switched?
I use buttons with images that act like radio buttons. i.e. an off image and an on image. The nice thing about this approach is it is very simple to implement and you can use the image to control the state of the button control. It works as a simple toggle and no fancy button state is needed. You can easily add code to the method that does something when buttons are on or off, in the example I just call a method which is writing some user defaults.
It should be quite easy to adapt to create radio button functionality.
-(IBAction)tickboxControl:(id)sender{
NSLog(#"%s",__FUNCTION__);
bgImageOn = [UIImage imageNamed:#"tickedBox.png"];
bgImageOff = [UIImage imageNamed:#"tickBoxEmpty.png"];
UIButton *buttonClicked = (UIButton *)sender;
UIImage *imageOfClicked = [buttonClicked imageForState:UIControlStateNormal];
if (imageOfClicked == bgImageOff) {
[self setButtonFlags: [NSNumber numberWithInt:[sender tag]] : [NSNumber numberWithInt:1] ];
[buttonClicked setImage:bgImageOn forState:UIControlStateNormal];
} else{
[self setButtonFlags: [NSNumber numberWithInt:[sender tag]] : [NSNumber numberWithInt:0] ];
[buttonClicked setImage:bgImageOff forState:UIControlStateNormal];
}
}
I created a project that shows exactly how to achieve what you are asking to do.
You can change the graphics from checkboxes (which I find a little better to see and understand on a device) to radio buttons.
Read the debug log to understand the logic.
If you have any questions give me a shout.
Radio Buttons Example Project (XCode4)
[this is in reply to your comments below]
I also used a custom UISegmentedControl. Something like this:
NSMutableArray* buttons;
- (void)touchDownAction:(UIButton*)button {
[self dimAllButtonsExcept:button];
if ([delegate respondsToSelector:#selector(touchDownAtSegmentIndex:)])
[delegate touchDownAtSegmentIndex:[buttons indexOfObject:button]];
}
-(void) dimAllButtonsExcept:(UIButton*)selectedButton {
for (UIButton* button in buttons) {
if (button == selectedButton) {
button.selected = YES;
button.highlighted = YES;
} else {
button.selected = NO;
button.highlighted = NO;
}
}
}
The full code is at https://github.com/j4n0/jobsket/tree/master/sources/main/ui/custom/segControl
I’ve used a UISegmentedControl as radio buttons.
Try this for a radio button in iOS:
#interface RadioButtonViewController : UIViewController
{
//for radio button
IBOutlet UIButton *radioButton1;
IBOutlet UIButton *radioButton2;
IBOutlet UITextField *selectedValue;
IBOutlet UILabel *label1;
IBOutlet UILabel *label2;
}
#property (nonatomic,retain) IBOutlet UIButton *radioButton1;
#property (nonatomic,retain) IBOutlet UIButton *radioButton2;
#property (nonatomic,retain) IBOutlet UITextField *selectedValue;
-(IBAction)userChangedButtonClicked:(id)sender
#end
Write code in .m file and specify the default and selected image in storyboard inspector window and give the tag value each button.
RadioButtonViewController.m
-(IBAction)userChangedButtonClicked:(id)sender
{
UIButton *senderBtn = (UIButton*)sender;
if (senderBtn.tag == 101 && !self.radioButton1.selected)
{
self.radioButton1.selected = TRUE;
self.radioButton2.selected = FALSE;
selectedValue.text = label1.text;
}else if (senderBtn.tag == 102 && !self.radioButton2.selected)
{
self.radioButton1.selected = FALSE;
self.radioButton2.selected = TRUE;
selectedValue.text = label2.text;
}
}
I have multiple UIButtons in my app. I also use interfacebuilder. In my .h i have something like this
IBOutlet UIButton *button1;
IBOutlet UIButton *button2;
IBOutlet UIButton *button3;
- (IBAction)buttonPressed;
Then In my m i want to do something like this
- (IBAction)buttonPressed {
if (theButtonIpressed == button1)
{
// do something if
}
}
The problem is I don't have something called "theButtonIpressed" so I cant do this. What should my if statement look like? I don't want to make a -(IBAction) for each button. Is there something that I can determine which button was pressed? Thanks!
Thanks,
-David
You can also set the tag property for each button in the interface builder and then use it to find out which button was pressed.... This also means that you don't need to define all your button references (UIButton) and keep track of them in code....
- (void) doSomething:(id)sender {
int buttonPressed = [sender tag];
switch (buttonPressed) {
case 0:....
// etc
}
}
Define your - (IBAction)buttonPressed to:
- (IBAction)buttonPressed: (UIButton *) buttonIpressed
Then it will work.
- (IBAction)buttonPressed:(UIButton*)button
But if you're doing something different for each button then the proper way to do it is to create separate IBActions.
You can use tag values for each buttons
IBOutlet UIButton *button1;
button1.tag = 100;
IBOutlet UIButton *button2;
button2.tag = 200;
IBOutlet UIButton *button3;
button3.tag = 300;
- (IBAction)buttonPressed:(id)sender
{
if ([sender tag]==100)
{
NSLOG("button1");
}
else if([sender tag]==200)
{
NSLOG("button2");
}
else {
NSLOG("button3");
}
}