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.
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;
}
How can I tell programmatically if a IBAction has been called by code or by user action.
Eg
I have a method, -(IBAction)someMethodWithIts:(id)sender
which I have linked to a valueChanged on a UISegmentedControl.
It can be called by,
User changing segment
setting the selectedIndex in code
calling [self someMethodWithIts:foo];
Is there a way to distinguish if the call has come from the first way?
Cheers
Sam
If you can pass nil as the sender (which is traditional) and use that to indicate it was sent programmatically, that's ok. But anything else I believe is too fragile and you should break up the code like this:
- (void)someMethod {
// stuff shared by everyone
}
- (IBAction)someMethodWithIts:(id)sender {
// stuff specific to IBAction
[self someMethod];
}
If you really want a sender, then you can do it this way:
- (void)someMethodWithIts:(id)sender triggeredByUser:(BOOL)isUser {
}
- (IBAction)someMethodWithIts:(id)sender {
[self someMethodWithIts:sender triggeredByUser:YES];
}
But in general, if you want the IBAction to be different than programatic changes, then don't wire programatic changes to the IBAction.
if ([sender isKindOfClass:[UIControl class]]) {
UIControl *controlSender = (UIControl *)sender;
if (sender.selected) {
// then it's #1
} else {
// then it's #2
}
} else if ([sender isKindOfClass:[Foo class]]) {
// then it's #3
}
Might work. Or poke around other properties of sender defined on UIControl or UISegmentedControl. Maybe state. My guess is you can find something that's different when the user is interacting vs. when they're not.
You really want to use method like this
-(IBAction)actionWithSender:(id)sender event:(UIEvent*)event
{
if (event) {
} else {
}
}
If you find the event parameter is nil, it's from a call in your code, otherwise, the call is from user event.
I am fairly new to iphone programming and here I am facing some issues. Now in my application, I have two textfields and I want to fire an event while second textfield starts editing. now I am using following function
- (void)textFieldDidBeginEditing:(UITextField *)textField
but the thing is the event is being fired when the first textfield starts editing. It does not wait for the second text field. Is there any way I can use this function for the second textfield or may be somehow could know and pass it the value of the active textfield?
I tried writing the name of the textfield instead of (UITextField *)textField in the function but still the same result.
If I were you , I would set a tag (in Interface Builder) of the second textField to 2, or something similar. Then you can just do this:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if (textField.tag == 2) {
//this is textfield 2, so call your method here
}
}
EDIT: Please do this to see if the method is even called:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(#"The method was called");
}
For Swift 2.2
func textFieldDidBeginEditing(textField: UITextField) {
if textField.tag == 2 {
//this is textfield 2, so call your method here
}
}
That delegate method is gonna get called everytime the editing of ANY text field is started, so it should be you who controls what is done when this happens. I suggest you to do something like:
-(void)textFieldDidBeginEditing: (UITextField *)textField
{
if (textField == mySecondTextField)
{
//Do what you need
}
else
{
//Do nothing
}
}
I hope it helps you!
Utilitize the tag property in Interface Builder to identify your view objects in your application at runtime. It will make life a lot easier, especially when you get ready to localize your application for different languages.
In your header file for your view controller
#define kUsernameField 100
#define kPasswordField 101
#define kStartButton 300
In the view controller implementation file
- (void)textFieldDidBeginEditing:(UITextField *)textField {
switch (textField.tag) {
case kUsernameField:
// do user name stuff
break;
case kPasswordField:
// do password stuff
break;
default:
NSLog(#"No case statement for %#", [textField description]);
break;
}
}
You will find a lot of tutorial out there that use the title field of UIButton to identify them. For example:
- (IBAction)buttonTouchUp:(id)sender {
UIButton *button = (UIButton *)sender;
// don't like
if ([button.currentTitle isEqualToString:#"Start"] == NSOrderedSame) {
// because if localize your for other language then you will have
// include code for those other language
// French: Démarrer
// Spanish: Inicio
// blah blah blah
}
// better
if (button.tag == kStartButton) {
// very simple, no code changes for localization
// blah blah blah
}
}
If you are creating the object with code, you can set the tag:
button.tag = kStartButton;
// or
[button setTag:kStartButton];
You must declare first UITextFieldDelegate in your controller .h
And set the delegate of your text field. ex. myInput.delegate = self;
-(void)textFieldDidBeginEditing:(UITextField *)sender
{
if ([sender isEqual:myInput])
{
NSLog(#"test");
}
}
This works perfectly for me.
Have you checked if your second textViews delegate is set to self ? I had the same issue where I had forgotten to set the delegate of other textFields and hence the delegate method was not firing.
Please have a look to my answer in this Question, it's exactly what you're looking for
Objective C: what is a "(id) sender"?
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;
}
I am trying to make a back button in my navigation bar because i already have a tab bar at the bottom of the screen.
my layout is this:
tab bar[
navigation bar {
webview ()
}
]
essentially. i need to programmatically add a back button and cannot seem to figure out how. i know that there is a goBack method but am not very familiar with how to implement this.
I already have a button which pulls up ana action sheet with several options but how would i go about having that use the goBack method?
as I understand I can also use something like
if (mywebview canGoBack) {
[mywebview goBack]
}
but I'm not sure how to make an action sheet button do this.
any help?
Somewhere in your action sheet's delegate file, you should have a method similar to this:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) { // if the first option is selected, whatever it may be... (counting starts at zero))
if ([myWebView canGoBack]) {
[myWebView goBack];
}
}
else return;
}