I'm trying to use a switch statement to read out what button has been clicked in a UIActionSheet (programming for iPhone).
The following is in my FirstViewController.m:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
int countarray=[areaselectArray count];
switch (buttonIndex) {
case countarray: //cancel button has been pressed
//do stuff
break;
default:
area = [areaselectArray objectAtIndex:(buttonIndex)];
[[NSUserDefaults standardUserDefaults] setObject:area forKey:#"mulValue"];
[areaselectArray release];
NSLog(#"Released areaselectArray");
break;
}
}
The buttons for the UIActionSheet are built from an array that I built earlier (and have not yet released). I'm placing my Cancel button at the end of the list by using
int countarray=[areaselectArray count];
[areaselect.cancelButtonIndex = countarray;]
earlier on when allocating my UIActionSheet. Since the amount of buttons changes depending on the amount of entries in the array, I'd like the "Cancel" button to simply dismiss the UIActionSheet, but in all other instances have the Switch statement write the value of the clicked button to "mulValue" in standardUserDefaults.
Is there any way to do this? My main issue right now of course is that a switch function won't take a variable (like countarray in my example). Is there any way to write the value to a constant (?) before entering the switch statement?
Thanks in advance!
Why don't you use if-statement instead of switch-statement? You can use cancelButtonIndex property for detecting pressing cancel button.
if (buttonIndex == actionSheet.cancelButtonIndex) {
// cancel button has been pressed
// do stuff
}
Also, you are able to use title string for comparison of buttons. However, button titles might be localized. Be careful.
NSString *buttonTitle = [actionSheet buttonTitleAtIndex:buttonIndex];
if ([buttonTitle isEqualToString:#"Cancel"]) {
// cancel button has been pressed
// do stuff
} else {
//
}
As you've discovered, only a constant can follow 'case'. The values with which a variable will be compared in a switch statement must be known at compile time.
To gain the functionality you desire, use an if/else construct. Simple as that. ;)
edit:
And, no, this will not compile (due to what I mentioned previously):
int n = 4;
const int a = someVariable;
switch (n) {
case a:
printf("hi");
break;
}
Related
I have a huge crazy scene in my story board that has 36 different buttons, and each one means something different when clicked on. I really don't want to go about creating 36 different methods, so how could I reference a button title or button name in a method that is called when one of the 36 buttons is pushed.
This is probably a simple question, but I'm new to iOS and Objective C...
Thanks!
You can create a single method, like so:
- (IBAction)buttonTapped:(id)sender{
// The button that was tapped is called "sender"
// This will log out the title of the button
//NSLog(#"Button: %#", sender.titleLabel.text);
//Edit: You need a cast in the above line of code:
NSLog(#"Button: %#", ((UIButton *)sender).titleLabel.text);
}
Then, you can use Interface Builder to connect to all of the buttons. You can have some sort of if/else logic to test which button was tapped.
You can check the titleLabel property, or you can assign an IBOutlet to each button and check for that.
For example:
if([sender isEqual:buttonOutlet1]){
//If this button is attached to buttonOutlet1
//do something
}
Alternatively, you can simply use the label of each button, not worrying about outlets.
A third option would be to generate and lay out the buttons in code, and then access them as elements of an array of buttons.
A fourth option would be to add tags to the buttons and check for the button's tag in your function.
Give each button a unique tag value. in the IBAction, sender.tag tells you which button was tapped.
The IBAction routine you set up to handle the button presses has a sender parameter. Examine that to decide.
-(IBAction) buttonPress: (id) sender {
UIButton *pressedButton = (UIButton *)sender;
NSString *buttonTitle = [pressedButton currentTitle];
if ([buttonTitle isEqualToString: #"SomeTitle"]) {
//do work for that button.
}
}
You can use a variety of NSString methods to compare or filter which button was pressed and handle it through if's or switches.
That's quite simple, but since you're new, here's an answer.
(According to Stanford cs193p course, 2010-2011 fall (that's what they did with the calculator app)) make a method that receives an argument, which is the UIButton.
for example:
- (IBAction) someMethodThatDoesSomething:(UIButton *)sender;
Then make if statements according to the sender.titleLabel.text
I don't know if there are any other solutions. Hope this helps!
-(IBAction)myButtonAction:(id)sender {
if ([sender tag] == 0) {
// do something here
}
if ([sender tag] == 1) {
// Do some think here
}
}
// in Other words
-(IBAction)myButtonAction:(id)sender {
NSLog(#"Button Tag is : %i",[sender tag]);
switch ([sender tag]) {
case 0:
// Do some think here
break;
case 1:
// Do some think here
break;
default:
NSLog(#"Default Message here");
break;
}
In my iPhone app, I have array of buttons that are dynamically generated based on user selection.
How do I distinguish selected button from others?
I want that when user select the other button the previously selected button should go back to its normal state in terms of its looks. I am unable to revert the previously selected buttons to its normal state.
Use tag to identify the button.
At the time of creating buttons you can assign tag as number to the button and use the same to identify.
yourButton.tag = intNumber;
You have an array of the buttons. You can loop through your array and check if it is the one that was clicked.
- (IBAction) buttonClicked:(id)sender {
for(int i; i < [array count]; i++){
if((UIButton *)sender == (UIButton *)[array objectAtIndex:i])
//do something
else
//do something else
}
Something like that.
Try setting tag for each button,using
yourButton.tag=intValue; //intValue>0
Your buttonAction should be as follows,
-(IBAction)buttonAction:(id)sender
Save the previously selected tag, and change the value accordingly.
you can loop through your subviews and set for all the old style:
- (void)highlightImgWithID:(int)packID {
[self.view.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UIImageView class]]) {
[(UIImageView*)obj setHighlighted:([obj tag] == IDtoSelectNext)];
}
}];
}
The sample is how I currently implement it in my App with UIImageView's you can change it to work with buttons.
I want to make a custom keyboard for my app and want to use the send button to set a character.
If I name all my buttons e.g. *a, *b, *c, *d etc. will it work to have one IBAction which takes the sender, grabs the name e.g. *a > a ? If so, how is this done.
Also, can a button be named as follows *0, *1, *2 rather than *zero, *one, *two?
Thanks
No, variables don't really work that way. You are confusing the object itself with the name of the variable that points to it. When your IBaction is passed the UIButton object, it's not passing a variable name along with it, your method defines the variable that references it as sender. And no, variable names cannot start with a digit in Objective C.
A common approach to differentiating between buttons in this way is to set the tag and branch on that. Alternatively, you can access the title - it depends on exactly what you are doing.
If you mean you want to point multiple UIButtons at the same IBAction and then extract the textual label of the button, you can simply use the currentTitle property of the sender.
For example:
- (IBAction)padButtonClicked:(id)sender {
NSLog(#"Button pressed: %#", [sender currentTitle]);
}
You are better off using tags for your buttons.
- (IBAction)buttonTapped:(id)sender {
NSLog(#"Button pressed: %i", sender.tag);
switch (sender.tag) {
case 0:
/* Button A Pressed */
break;
case 1:
/* Button B Pressed */
break;
/* and so forth... */
}
}
You will need to set the tags either in Interface Builder, or programmatically.
I have 3 alert views in my apps.
'wonAlert'
'lostAlert'
'nagAlert'
I implement this to give them actions.
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
This used to work fine, when I had just the 'wonAlert' and 'lostAlert', they had a dismiss and a learn more button that took them to wikipedia,
now I want the nag alert to take them to the app store.
how can I make it so the above method knows which alert view the tap is coming from, or something like that?
Cheers, Sam
It sounds like you've got the UIAlertViews in variables, so I'd use them:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView == wonAlert) {
//DO STUFF
}
else if (alertView == lostAlert) {
//DO OTHER STUFF
}
else if (alertView == nagAlert) {
//OPEN APP STORE
}
}
More than one view can have the same tag and you can easily mistype the title or change it and forget to update the delegate method.
In your view controller header file, add <UIAlertViewDelegate> so that it agrees to handle UIAlertView delegate methods:
#interface MyViewController : UIViewController <UIAlertViewDelegate> { ... }
In the implementation of your view controller, add the following delegate method:
- (void) alertView:(UIAlertView *)_actionSheet clickedButtonAtIndex:(NSInteger)_buttonIndex {
if ([_actionSheet.title isEqualToString:#"titleOfMyAlertView"]) {
if (_buttonIndex == 0) {
// do stuff for first button
}
else if (_buttonIndex == 1) {
// do something for second button
}
// etc. if needed
}
}
The _actionSheet.title property can be used to distinguish between alert views. My recommendation is to use NSString constants or NSLocalizedString(), if you have a localized strings table, to title your alert views.
I answered a similar question here:
Alert with 2 buttons
the correct way to do this is using the tag property of alerts
upon creating each alert, set its tag variable by adding:
alertName.tag = #; //ex: alertName.tag = 1
Then, in the clickedButtonAtIndex method, you will need to add an 'if' block for each alert you have as shown in the folllowing code:
if(alert.tag == 1)
{
if (buttonIndex == 0)
{
//do stuff
}
else
{
//do other stuff
}
}
if(alert.tag == 2)
///...etc
I would do what Alex suggests, but use the tag property of the AlertView to determine which AlertView had been used.
I am using the actionSheet variable passed by actionSheet:didDismissWithButtonIndex: to compare the calling actionSheet to a list of UIActionSheet variables in my class. This seems to be the way the delegate method was designed to differentiate between events.
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (actionSheet == actionSheet1) {
switch (buttonIndex) {
case 0:
// Do Something
break;
case 1:
// Do Something Else
break;
case 2:
// Cancel
break;
}
}
if (actionSheet == actionSheet2) {
switch (buttonIndex) {
case 0:
// Do Something
break;
case 1:
// Do Something Else
break;
case 2:
// Cancel
break;
}
}
}
Each time a UIActionSheet is displayed, I alloc an instance of UIActionSheet to one of the class variables, set the display properties, display it, and release it.
This works smoothly, at first. The problem is that after running for a while, eventually both UIActionSheet pointers (class variables actionSheet1 & actionSheet2 in the code example above) will end up pointing to the same memory, depending on what happens at runtime, thereby causing both if statements in the delegate method to evaluate true. Not good.
Now, if I were to alloc each UIActionSheet only once per run and hold on to the memory (never call release), this should not happen. But I am trying to be conservative here. Does Apple intend for the delegate to be used in this way?
When you create your UIActionSheet, give it a tag:
actionSheet.tag = 1; // or 2 or 3 or ...
Then, in your delegate method, switch based on the tag to determine the behavior of that particular sheet.