Multiple UIActionSheets on the same delegate - iphone

I'm writing a puzzle game. When the user presses the check button, I see if the solution they entered is correct. Depending on the result, I present one of two action sheets for them. For now I just have some NSLog statements to make sure things are getting called, but only one of the sheets seems to work properly.
Nothing gets called when I click a button in showErrorsActionSheet. The action sheet disappears off the screen, but the logs never print.
I suspect it has something to do with having two actionsheets declared to the same delegate (self)
- (void) checkSolution {
//code determines the value of the BOOL allCorrect
if (allCorrect) { //IF ALL OF THE LETTERS WERE CORRECT
//display UIAlertView;
NSLog(#"allCorrect");
UIActionSheet *levelCompleteActionSheet = [[UIActionSheet alloc] initWithTitle:#"Congratulations! You Have Finished the Level!" delegate:self cancelButtonTitle:#"Review my work" destructiveButtonTitle:#"Choose next puzzle" otherButtonTitles:nil, nil];
[levelCompleteActionSheet showInView:self.view];
[levelCompleteActionSheet release];
}
else {
//[self showIncorrectLettersInRed];
UIActionSheet *showErrorsActionSheet = [[UIActionSheet alloc] initWithTitle:#"Sorry, thats not right. Show errors in red?" delegate:self cancelButtonTitle:#"No Thanks, I'll keep trying" destructiveButtonTitle:#"Yes please, I'm stuck!" otherButtonTitles:nil, nil];
[showErrorsActionSheet showInView:self.view];
[showErrorsActionSheet release];
}
}
the methods that are supposed to be called are:
- (void) levelCompleteActionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex != [actionSheet cancelButtonIndex]) {
NSLog(#"return to levelSelect");
//pushViewController:levelSelect
}
else {
NSLog(#"continue to examine solution");
}
}
- (void) showErrorsActionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex != [actionSheet cancelButtonIndex]) {
NSLog(#"show errors in red");
}
else {
NSLog(#"continue to try");
}
}
and Ive declared the UIActionSheet protocol in the interface file as follows:
#interface GamePlay : UIViewController <UIActionSheetDelegate> {

Set a tag for each actionSheet, then use a switch statement in the UIActionSheet delegate.
Assign a tag
- (void)checkSolution
{
if (allCorrect)
{
UIActionSheet *levelCompleteActionSheet = [[UIActionSheet alloc] initWithTitle:#"Congratulations! You Have Finished the Level!" delegate:self cancelButtonTitle:#"Review my work" destructiveButtonTitle:#"Choose next puzzle" otherButtonTitles:nil, nil];
[levelCompleteActionSheet setTag: 0];
[levelCompleteActionSheet showInView:self.view];
[levelCompleteActionSheet release];
}
else
{
UIActionSheet *showErrorsActionSheet = [[UIActionSheet alloc] initWithTitle:#"Sorry, thats not right. Show errors in red?" delegate:self cancelButtonTitle:#"No Thanks, I'll keep trying" destructiveButtonTitle:#"Yes please, I'm stuck!" otherButtonTitles:nil, nil];
[showErrorsActionSheet setTag: 1];
[showErrorsActionSheet showInView:self.view];
[showErrorsActionSheet release];
}
}
UIActionSheet Delegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch ( actionSheet.tag )
{
case 0: /* levelCompleteActionSheet */
{
switch ( buttonIndex )
{
case 0: /* 1st button*/
break;
case 1: /* 2nd button */
break;
}
}
break;
case 1: /* showErrorsActionSheet */
break;
}
}
The same would apply anywhere else in this class as well, including levelCompleteActionSheet: and showErrorsActionSheet:. The only difference is, you would need to create an iVar for each actionSheet instead of creating them in checkSolution.

The methods that will be called by a UIActionSheet on its delegate are the methods listed in the UIActionSheetDelegate protocol.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIModalViewDelegate_Protocol/UIActionSheetDelegate/UIActionSheetDelegate.html
To be called, your method must be one of those methods. I don't see levelCompleteActionSheet or showErrorsActionSheet listed in that protocol! :) Your method must be named actionSheet:clickedButtonAtIndex:, and not some name you make up out of whole cloth.

Using Tag solve this problem
levelCompleteActionSheet.tag = 100;
showErrorsActionSheet.tag = 101;
- (void) levelCompleteActionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if(actionSheet.tag == 100){
// levelCompleteActionSheet implement your required function
}
else if(actionSheet.tag == 101){
// showErrorsActionSheet implement your required function
}
}

Related

Can not dismiss an action sheet here

A UILongPressGestureRecognizer is added to my imageView with action handleLongPressOnPhotos. The most related codes is as following:
- (IBAction)handleLongPressOnPhotos:(UILongPressGestureRecognizer *)sender
{
self.imageWillBeSaved = (UIImageView *)sender.view; //breakPoint1
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Save the photo" otherButtonTitles: #"Go to the Original photo", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
[actionSheet showInView:self.view]; //breakPoint2
NSLog( #"actionSheet addr when created is %p", actionSheet );//breakPoint3
[actionSheet release];//breakPoint4
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
case 0:
UIImageWriteToSavedPhotosAlbum(self.imageWillBeSaved.image, self, #selector(image: didFinishSavingWithError:contextInfo:), nil);
//[actionSheet dismissWithClickedButtonIndex:0 animated:YES]; i have tried to use this method here, but it didn't work.
break;
default:
break;
}
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error != NULL)
{
// handle error
}
else
{
// handle ok status
}
}
The action sheet will not be dismissed after i click the "save the photo" button. If i click the button again, the action sheet dismissed and the photo saved twice.Any problem in the code? Thanks in advance!
Ps. the imageView is a subview of a scrollView, and the scrollView is in a tableViewCell.
- (IBAction)handleLongPressOnPhotos:(UILongPressGestureRecognizer *)sender
{
self.imageWillBeSaved = (UIImageView *)sender.view; //breakPoint1
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:#"Cancel" destructiveButtonTitle:#"Save the photo" otherButtonTitles: #"Go to the Original photo", nil];
actionSheet.actionSheetStyle = UIActionSheetStyleDefault;
[actionSheet showInView:self.view]; //breakPoint2
NSLog( #"actionSheet addr when created is %p", actionSheet );//breakPoint3
[actionSheet release];//breakPoint4
}
I set two breakpoint in the "handleLongPressOnPhotos:" method as breakPoint1 and breakPoint1. I followed the steps of the code after the imageView was longPressed. The step order is :breakPoint1 -> breakPoint2 ->breakPoint1 ->breakPoint2 - > breakPoint3 -> breakPoint4 - > breakPoint3 -> breakPoint4, then went out. It is obvious that the actionSheet has been presented twice, that cause the problem. It is odd, and I do not know the reason and avoid this.
Problem solved in another question UILongPressGestureRecognizer gets called twice when pressing down
thanks to #Laddu, #MichaelDautermann, #sreecharan
IT Looks OK but please add nslog here:-
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
NSLog(#"buttonIndex.....%d",buttonIndex);
switch (buttonIndex) {
case 0:
UIImageWriteToSavedPhotosAlbum(self.imageWillBeSaved.image, self, #selector(image: didFinishSavingWithError:contextInfo:), nil);
//[actionSheet dismissWithClickedButtonIndex:0 animated:YES]; i have tried to use this method here, but it didn't work.
break;
default:
break;
}
}
Check you add ACtionSheet Delegate in .h file also .
is there a reason why you are not using actionSheet:willDismissWithButtonIndex: instead of actionSheet:clickedButtonAtIndex:.
If you use actionSheet:willDismissWithButtonIndex:, you don't need to care about dismissing the ActionSheet yourself.
Problem solved in another question UILongPressGestureRecognizer gets called twice when pressing down
thanks to #Laddu, #MichaelDautermann, #sreecharan

UIAlertViewStylePlainTextInput - Program continues without waiting for text input from user

I'm sort of stuck on a UIAlertViewStylePlainTextInput. (My code is too long to post here, but this is the part where the problem exists.) It all sort of works, but the program doesn't wait until the user enters the information before continuing. The "editName" button doesn't change the display in the code below, but the updateDisplay button works fine (if you've pressed the "editName" button before you pressed "updateDisplay"). How can I get everything to sort of halt until the user enters the info (or cancels). Or is there some other lead that will take me where I need to go. (I've been toying with putting the rest of the code in the -(void) alertView, but that just doesn't seem to be the correct way of doing it).
Thanks in advance.
#import "HSTestViewController.h"
#implementation HSTestViewController
#synthesize display;
NSString *newName;
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 1)
{
newName = [[alertView textFieldAtIndex:0] text];
}
}
- (void) getNewName;
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"You made the High Score List"
message:#"Please enter your name"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
}
- (IBAction)editName:(id)sender
{
[self getNewName];
newName = display.text;
}
- (IBAction)updateDisplay:(id)sender
{
display.text = newName;
}
#end
Add UIAlertViewDelegate to the class. And implement the below delegate method.
OK button index value will be 1 in your case.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex)
{
// call the method or the stuff which you need to perform on click of "OK" button.
}
}
Hope this helps.

iPhone/Objective-C UIActionSheet with programmatically added buttons

I have a UIActionSheet that contains buttons that are programmatically added depending on whether a property contains a value or not.
This is the code I'm currently using:
- (IBAction)infoButtonTap:(id)sender {
MyObject *obj = (MyObject *)[self.dataSource objectAtIndex:self.pageControl.currentPage];
if (obj != nil) {
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:#"Details"
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
// Programatically add Other button titles if they exist.
if (obj.firstProperty) {
[actionSheet addButtonWithTitle:#"Dosomething"];
}
if (obj.secondProperty) {
[actionSheet addButtonWithTitle:#"Dosomethingelse"];
}
[actionSheet addButtonWithTitle:#"Static button"];
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:#"Cancel"];
[actionSheet showInView:self.view.window];
[actionSheet release];
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
MyObject *obj = (MyObject *)[self.dataSource objectAtIndex:self.pageControl.currentPage];
switch (buttonIndex) {
case 0: // Dosomething
break;
case 1: // Dosomethingelse
break;
case 2: // Static button
break;
default:
break;
}
}
The problem is, how do I account for the fact that one of the properties may be null and handle that within the clickedButtonAtIndex:? The index values will change. I have around 4 or 5 different buttons, each displayed depending on whether a property contains a value of some sort.
The simplest way is probably to use the buttonTitleAtIndex: method of UIActionSheet to get the button title and use this to determine what action to take.
Alternatively you could use logic similar to where you add the buttons to figure out exactly what the index means.

Show Alert in clickedButtonAtIndex?

i need to show a confirm alert after the user press buttonIndex 1 but... if i use popViewcontroller in clickedButtonAtIndex it crash without errors.
The problem is that
[self.navigationController popViewControllerAnimated:YES];
is called before second Alert click...
how to fix?
This is my code:
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:#"OK!"
message:#"Completed"
delegate:self
cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
[alert release];
[self.navigationController popViewControllerAnimated:YES];
}
}
Set the tag properties of the two UIAlertViews to 1 and 2, respectively. Then, in the delegate method, use if statements to check the tag of the UIAlertView argument.
Example:
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView.tag == 1)
{
//check the button index
//create and display the other alert view (set the tag property here to 2)
}
else if (alertView.tag == 2)
{
//pop the view controller
}
}

UIAlertView button tagging

Is there a way I can add a .tag to an UIAlertView button? Reason being, I'm adding a few dynamic buttons to the alert that will sometimes be in the alert and sometimes not. I figured the best way was to add a tag. Is there a better method for this?
The options that will ALWAYS be in the alert are Email, Save. And the 2 optional options are Tweet This and Facebook.
Thanks for any help in advance!
There is one method buttonTitleAtIndex for UIAlertView. Use that to find the button tapped by user.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *buttonString = [alertView buttonTitleAtIndex:buttonIndex];
if( [buttonString isEqualToString:#"Facebook"] ){
// your code here
} else if( [buttonString isEqualToString:#"twitter"] ){
// your code here
}
}
You can also use tag proprerty:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Info"
message:#"Info text"
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:nil, nil];
[alert setTag:0];
Then in delegate:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (alertView.tag) {
case 1: {
...
break;
}
...
default:
break;
}