- (void)alertViewCancel:(UIAlertView *)alertView is not called - iphone

I've got the problem that the UIAlertViewDelegate method - (void)alertViewCancel:(UIAlertView *)alertView is not called when I cancel a AlertView with it's cancel button.
Weird is that the delegate method - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex works perfectly.
Does anyone have an idea?
Thanks in advance
Sean
- (void)alertViewCancel:(UIAlertView *)alertView
{
if(![self aBooleanMethod])
{
exit(0);
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
//some code
}
I call this when a button is clicked:
- (void)ImagePickDone
{
UIAlertView *alertDone = [[UIAlertView alloc]
initWithTitle:#"Done"
message:#"Are u sure?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles: #"Yes", nil];
[alertDone show];
[alertDone release];
}

The alertViewCancel is used for when the system dismisses your alert view, not when the user presses the "Cancel" button. Quote from apple docs:
Optionally, you can implement the
alertViewCancel: method to take the
appropriate action when the system
cancels your alert view. If the
delegate does not implement this
method, the default behavior is to
simulate the user clicking the cancel
button and closing the view.
If you want to capture when the user presses the "Cancel" button you should use the clickedButtonAtIndex method and check that the index corresponds to the index for the cancel button. To obtain this index use:
index = alertDone.cancelButtonIndex;

You can handle the Cancel at the index 0 of this delegate:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0){
//cancel button clicked. Do something here.
}
else{
//other button indexes clicked
}
}

This can be improved in two ways. First, it only handles the case that the user actually clicked a button. It doesn't handle the situation that [myAlert dismissWithClickedButtonIndex:] is called, or that the alert is dismissed in some other way. Second, button 0 is not necessarily the cancel button. In an alert with two buttons, the left one is at index 0, and the right one is at index 1. If you changed the titles so that the right button says "Cancel", then button 1 is logically the Cancel button. Instead of "willDismiss" you can implement "didDismiss" which will be called after the dialog has disappeared and not before.
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == alertView.cancelButtonIndex)
{
//cancel button clicked. Do something here.
}
else
{
//other button indexes clicked
}
}

Related

How to distinguish between UIAlertView Cancel and UIAlertViewStyleSecureTextInput's TextView Return?

I have created a UIAlertView
alert = [[UIAlertView alloc] initWithTitle:#"Test"
message:#"Working"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert setAlertViewStyle:UIAlertViewStyleSecureTextInput];
alert.tag = kAlertTypePIN;
UITextField *textField = [alert textFieldAtIndex:0];
textField.delegate = self;
If I press Retun key in UIAlertView textfield it works fine, it calls:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[alert dismissWithClickedButtonIndex:0 animated:YES];
}
and then
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"didDismissWithButtonIndex");
// If no text or wrong text show alert again otherwise normal actions
}
But if I press the cancel button, it 1st calls textFieldDidEndEditing which in turn calls the alert delegate. And again it calls the alert delegate method by itself.
So alert to be displayed is not getting shown and keyboard starts to pop up and goes back. So no alert is being shown in case when its to be shown.
If any doubts in the flow, please ask me.
How can I rectify the issue?
unset the delegate of the textField in alertView:willDismissWithButtonIndex:
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
UITextField *textField = [alert textFieldAtIndex:0];
textField.delegate = nil;
}
When the alert is dismissed the textField will end editing, and afterwards it will call the textFieldDidEndEditing: delegate method.
If you set the delegate to nil before the dismissal starts, the delegate method can't be called.
Besides that, a better design would be to have a cancel button "Cancel", and an other button "Submit". When the textField ends you dismiss the alert with "Submit", and not "Cancel".
You simply want to hide UIAlertiView on cancel click?
Then if your cancel buttonindex is 1 then:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
if(buttonIndex == 1) {
[[alert textFieldAtIndex:0] resignFirstResponder];
}
}
try this condition.. as you dont want alert to be gone when Pin is not there...
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if([textField.text length]!=0)
[alert dismissWithClickedButtonIndex:0 animated:YES];
}
If you want to hide UIAlertiView on "Cancel" button click then just simply add this code to clickedButtonAtIndex:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 1)
{
[[alert textFieldAtIndex:0] resignFirstResponder];
}
}
Try this
Add UIAlertView following delegate method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
{
[[alert textFieldAtIndex:0] resignFirstResponder];
}

How to create UIAlertView with multiple options?

I am trying to work out how I can use a UIAlertView to do more than one command.
Basically, in my ViewController, there is already an alertView, however I am now adding some storekit files, which, require there own alertView (to tell it whether to purchase the in-app or cancel etc.
Here is original alertView code;
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[alertView dismissWithClickedButtonIndex:0 animated:NO];
if (buttonIndex == 1) {
[g_GameUtils removeAlbumFolder:deleteIndex];
[g_GameUtils readAllData];
[g_GameUtils getAlbumFolderList];
[m_pTable reloadData];
}
}
And here is what I need also - they are both called alertView so I cannot use both like this, is there a way to combine them? Or is it better to call one of them alertView2 ? If so, how does it know which one to call for the particular alert?
Thanks in advance!
Chris
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0){
//cancel button clicked. Do something here or nothing here
}
else{
//other button indexes clicked
[[MKStoreManager sharedManager] buyFeature:#"com.davis.apptoken.buy"];
}
}
Also you can use alertView.tag = 1; and alertView2.tag = 2; and add appropriate conditions to delegate:
if (alertView.tag == 1)
{
// First alert
}

Action Sheet Within ActionSheet

am new to Objective C and iPhone Development.
Kindly tell me how can i add an action sheet within action sheet.
Like when i tap a button an action sheet is opened and then I clicked the first ButtonIndex of action another action sheet appears.
Kindly mention the complete code.
Thanks
Use the UIActionSheet delegate method:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) { // Add an action sheet for one of these buttons -> maybe here if you want...
NSLog(#"You clicked the first button...");
UIActionSheet *popupQuery = [[UIActionSheet alloc] initWithTitle:#"Another action sheet"
delegate:self cancelButtonTitle:#"Cancel Button" destructiveButtonTitle:#"Destructive"
otherButtonTitles:#"Other Button 1", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
[popupQuery showInView:self.view];
[popupQuery release];
}
else {
NSLog(#"Dismissing action sheet");
}
}
All you want to do is dismiss the first UIActionSheet and show another UIActionSheet in it's place. In other words, you don't want to show a UIActionSheet within another UIActionSheet -- you want to show a UIActionSheet after a different UIActionSheet has been dismissed.
To find out when an action sheet is being dismissed, you should implement the UIActionSheetDelegate protocol. For example:
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
// first action sheet is dismissed
// show a new action sheet here
}

UIActionSheet from UIAlertView

I'm trying to show a UIActionSheet when the user touches a button in a UIAlertView:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
UIActionSheet *actionSheet = ...
[actionSheet showFromTabBar:self.tabBarController.tabBar];
}
}
When the action sheet is shown the alert view is still on the screen behind the action sheet, and when I touch a button in the action sheet - the action sheet disappears but the whole screen is dimmed with the alert view still on and I can't dismiss it.
I tried several things, such as showing the action sheet after a short delay or dismissing the alert view programmatically, but nothing worked. In the best case (dismissing the alert view programmatically) the alert view did disappear after a somewhat-strange transition but I got a "wait-fence failed to receive reply" error in the log when it did.
How can I show an action sheet from an alert view in an orderly manner?
In this case, you should use
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
method rather than,
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
so your code wil be:
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
UIActionSheet *actionSheet = ...
[actionSheet showFromTabBar:self.tabBarController.tabBar];
}
}
Thanks,
Just call dismissWithClickedButtonIndex:animated: method for UIAlertView
if (buttonIndex == 0)
{
[alertView dismissWithClickedButtonIndex:0 animated:YES];
UIActionSheet *actionSheet = ...
[actionSheet showFromTabBar:self.tabBarController.tabBar];
}

Detecting button pressed when there are multiple alert views

I have multiple alert views in one view, and I use this code to detect which button was pressed:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if ([title isEqualToString:#"OK"]) {
//for one alert view
[passCode becomeFirstResponder];
} else if ([title isEqualToString:#" OK "]) {
//for another alert view, had to change "OK" to " OK "
[passCodeConfirm becomeFirstResponder];
}
}
Now since there are multiple alert views in one view that do different things, I have to trick the user into thinking "OK" and " OK " are the same thing. It works and looks fine, but it feels kind of messy. Surely there is another way to do this, such as making this specific to an alert view, and then making it specific to another. Do you know how I would do this? Thanks!
It would be more technical as well better that set unique tag for separate UIAlertView and identify it and access in its delegate method.
For example,
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Message" message:#"Are You Sure you want to Update?" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert setTag:1];
[alert show];
[alert release];
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView.tag == 1)
{
// set your logic
}
}
Use tag property to uniquely identify each of the alertview u create.
Like this
myAlertView.tag = 1
Then in the clickedButtonAtIndex delegate method check which alertview's button was clicked using this tag property ,
if(alertView.tag==1)
I wouldn't use the titles to distinguish between the buttons. You'll run into problems when your app is localized or you decide to change the button titles, but forget to update them everywhere. Use the button indexes instead or if you only have one button in addition to a cancel button, use the cancelButtonIndex property of UIAlertView.
To distinguish between multiple alert views, you could use their tag property.
In your view, add a property for each alert view.
UIAlertView *myAlertType1;
UIAlertView *myAlertType2;
#property (nonatomic, retain) UIAlertView *myAlertType1;
#property (nonatomic, retain) UIAlertView *myAlertType2;
Create your alert using these properties
self.myAlertType1 = [[[UIAlertView alloc] initWithTitle: ... etc] autorelease];
[self.myAlertType1 show];
Then in your delegate method:
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView == myAlertType1) {
// check the button types and add behaviour for this type of alert
} else if (alertView == myAlertType2 {
// check the button types and add behaviour for the second type of alert
}
}
Edit: Although the above works, iApple's suggestion of using the tag seems cleaner/simpler.
//in your .h file
UIAlertView* alert1;
UIAlertView* alert2;
//in your .m file
// when you are showing your alerts, use
[alert1 show]; //or
[alert2 show];
//and just check your alertview in the below method
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(alertView == alert1)
{
//check its buttons
}
else //check other alert's btns
}